| .. _pgpguide: | 
 |  | 
 | =========================== | 
 | Kernel Maintainer PGP guide | 
 | =========================== | 
 |  | 
 | :Author: Konstantin Ryabitsev <konstantin@linuxfoundation.org> | 
 |  | 
 | This document is aimed at Linux kernel developers, and especially at | 
 | subsystem maintainers. It contains a subset of information discussed in | 
 | the more general "`Protecting Code Integrity`_" guide published by the | 
 | Linux Foundation. Please read that document for more in-depth discussion | 
 | on some of the topics mentioned in this guide. | 
 |  | 
 | .. _`Protecting Code Integrity`: https://github.com/lfit/itpol/blob/master/protecting-code-integrity.md | 
 |  | 
 | The role of PGP in Linux Kernel development | 
 | =========================================== | 
 |  | 
 | PGP helps ensure the integrity of the code that is produced by the Linux | 
 | kernel development community and, to a lesser degree, establish trusted | 
 | communication channels between developers via PGP-signed email exchange. | 
 |  | 
 | The Linux kernel source code is available in two main formats: | 
 |  | 
 | - Distributed source repositories (git) | 
 | - Periodic release snapshots (tarballs) | 
 |  | 
 | Both git repositories and tarballs carry PGP signatures of the kernel | 
 | developers who create official kernel releases. These signatures offer a | 
 | cryptographic guarantee that downloadable versions made available via | 
 | kernel.org or any other mirrors are identical to what these developers | 
 | have on their workstations. To this end: | 
 |  | 
 | - git repositories provide PGP signatures on all tags | 
 | - tarballs provide detached PGP signatures with all downloads | 
 |  | 
 | .. _devs_not_infra: | 
 |  | 
 | Trusting the developers, not infrastructure | 
 | ------------------------------------------- | 
 |  | 
 | Ever since the 2011 compromise of core kernel.org systems, the main | 
 | operating principle of the Kernel Archives project has been to assume | 
 | that any part of the infrastructure can be compromised at any time. For | 
 | this reason, the administrators have taken deliberate steps to emphasize | 
 | that trust must always be placed with developers and never with the code | 
 | hosting infrastructure, regardless of how good the security practices | 
 | for the latter may be. | 
 |  | 
 | The above guiding principle is the reason why this guide is needed. We | 
 | want to make sure that by placing trust into developers we do not simply | 
 | shift the blame for potential future security incidents to someone else. | 
 | The goal is to provide a set of guidelines developers can use to create | 
 | a secure working environment and safeguard the PGP keys used to | 
 | establish the integrity of the Linux kernel itself. | 
 |  | 
 | .. _pgp_tools: | 
 |  | 
 | PGP tools | 
 | ========= | 
 |  | 
 | Use GnuPG v2 | 
 | ------------ | 
 |  | 
 | Your distro should already have GnuPG installed by default, you just | 
 | need to verify that you are using version 2.x and not the legacy 1.4 | 
 | release -- many distributions still package both, with the default | 
 | ``gpg`` command invoking GnuPG v.1. To check, run:: | 
 |  | 
 |     $ gpg --version | head -n1 | 
 |  | 
 | If you see ``gpg (GnuPG) 1.4.x``, then you are using GnuPG v.1. Try the | 
 | ``gpg2`` command (if you don't have it, you may need to install the | 
 | gnupg2 package):: | 
 |  | 
 |     $ gpg2 --version | head -n1 | 
 |  | 
 | If you see ``gpg (GnuPG) 2.x.x``, then you are good to go. This guide | 
 | will assume you have the version 2.2 of GnuPG (or later). If you are | 
 | using version 2.0 of GnuPG, then some of the commands in this guide will | 
 | not work, and you should consider installing the latest 2.2 version of | 
 | GnuPG. Versions of gnupg-2.1.11 and later should be compatible for the | 
 | purposes of this guide as well. | 
 |  | 
 | If you have both ``gpg`` and ``gpg2`` commands, you should make sure you | 
 | are always using GnuPG v2, not the legacy version. You can enforce this | 
 | by setting the appropriate alias:: | 
 |  | 
 |     $ alias gpg=gpg2 | 
 |  | 
 | You can put that in your ``.bashrc`` to make sure it's always the case. | 
 |  | 
 | Configure gpg-agent options | 
 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
 |  | 
 | The GnuPG agent is a helper tool that will start automatically whenever | 
 | you use the ``gpg`` command and run in the background with the purpose | 
 | of caching the private key passphrase. There are two options you should | 
 | know in order to tweak when the passphrase should be expired from cache: | 
 |  | 
 | - ``default-cache-ttl`` (seconds): If you use the same key again before | 
 |   the time-to-live expires, the countdown will reset for another period. | 
 |   The default is 600 (10 minutes). | 
 | - ``max-cache-ttl`` (seconds): Regardless of how recently you've used | 
 |   the key since initial passphrase entry, if the maximum time-to-live | 
 |   countdown expires, you'll have to enter the passphrase again. The | 
 |   default is 30 minutes. | 
 |  | 
 | If you find either of these defaults too short (or too long), you can | 
 | edit your ``~/.gnupg/gpg-agent.conf`` file to set your own values:: | 
 |  | 
 |     # set to 30 minutes for regular ttl, and 2 hours for max ttl | 
 |     default-cache-ttl 1800 | 
 |     max-cache-ttl 7200 | 
 |  | 
 | .. note:: | 
 |  | 
 |     It is no longer necessary to start gpg-agent manually at the | 
 |     beginning of your shell session. You may want to check your rc files | 
 |     to remove anything you had in place for older versions of GnuPG, as | 
 |     it may not be doing the right thing any more. | 
 |  | 
 | Set up a refresh cronjob | 
 | ~~~~~~~~~~~~~~~~~~~~~~~~ | 
 |  | 
 | You will need to regularly refresh your keyring in order to get the | 
 | latest changes on other people's public keys, which is best done with a | 
 | daily cronjob:: | 
 |  | 
 |     @daily /usr/bin/gpg2 --refresh >/dev/null 2>&1 | 
 |  | 
 | Check the full path to your ``gpg`` or ``gpg2`` command and use the | 
 | ``gpg2`` command if regular ``gpg`` for you is the legacy GnuPG v.1. | 
 |  | 
 | .. _master_key: | 
 |  | 
 | Protect your master PGP key | 
 | =========================== | 
 |  | 
 | This guide assumes that you already have a PGP key that you use for Linux | 
 | kernel development purposes. If you do not yet have one, please see the | 
 | "`Protecting Code Integrity`_" document mentioned earlier for guidance | 
 | on how to create a new one. | 
 |  | 
 | You should also make a new key if your current one is weaker than 2048 bits | 
 | (RSA). | 
 |  | 
 | Master key vs. Subkeys | 
 | ---------------------- | 
 |  | 
 | Subkeys are fully independent PGP keypairs that are tied to the "master" | 
 | key using certifying key signatures (certificates). It is important to | 
 | understand the following: | 
 |  | 
 | 1. There are no technical differences between the "master key" and "subkeys." | 
 | 2. At creation time, we assign functional limitations to each key by | 
 |    giving it specific capabilities. | 
 | 3. A PGP key can have 4 capabilities: | 
 |  | 
 |    - **[S]** key can be used for signing | 
 |    - **[E]** key can be used for encryption | 
 |    - **[A]** key can be used for authentication | 
 |    - **[C]** key can be used for certifying other keys | 
 |  | 
 | 4. A single key may have multiple capabilities. | 
 | 5. A subkey is fully independent from the master key. A message | 
 |    encrypted to a subkey cannot be decrypted with the master key. If you | 
 |    lose your private subkey, it cannot be recreated from the master key | 
 |    in any way. | 
 |  | 
 | The key carrying the **[C]** (certify) capability is considered the | 
 | "master" key because it is the only key that can be used to indicate | 
 | relationship with other keys. Only the **[C]** key can be used to: | 
 |  | 
 | - add or revoke other keys (subkeys) with S/E/A capabilities | 
 | - add, change or revoke identities (uids) associated with the key | 
 | - add or change the expiration date on itself or any subkey | 
 | - sign other people's keys for web of trust purposes | 
 |  | 
 | By default, GnuPG creates the following when generating new keys: | 
 |  | 
 | - A master key carrying both Certify and Sign capabilities (**[SC]**) | 
 | - A separate subkey with the Encryption capability (**[E]**) | 
 |  | 
 | If you used the default parameters when generating your key, then that | 
 | is what you will have. You can verify by running ``gpg --list-secret-keys``, | 
 | for example:: | 
 |  | 
 |     sec   rsa2048 2018-01-23 [SC] [expires: 2020-01-23] | 
 |           000000000000000000000000AAAABBBBCCCCDDDD | 
 |     uid           [ultimate] Alice Dev <adev@kernel.org> | 
 |     ssb   rsa2048 2018-01-23 [E] [expires: 2020-01-23] | 
 |  | 
 | Any key carrying the **[C]** capability is your master key, regardless | 
 | of any other capabilities it may have assigned to it. | 
 |  | 
 | The long line under the ``sec`` entry is your key fingerprint -- | 
 | whenever you see ``[fpr]`` in the examples below, that 40-character | 
 | string is what it refers to. | 
 |  | 
 | Ensure your passphrase is strong | 
 | -------------------------------- | 
 |  | 
 | GnuPG uses passphrases to encrypt your private keys before storing them on | 
 | disk. This way, even if your ``.gnupg`` directory is leaked or stolen in | 
 | its entirety, the attackers cannot use your private keys without first | 
 | obtaining the passphrase to decrypt them. | 
 |  | 
 | It is absolutely essential that your private keys are protected by a | 
 | strong passphrase. To set it or change it, use:: | 
 |  | 
 |     $ gpg --change-passphrase [fpr] | 
 |  | 
 | Create a separate Signing subkey | 
 | -------------------------------- | 
 |  | 
 | Our goal is to protect your master key by moving it to offline media, so | 
 | if you only have a combined **[SC]** key, then you should create a separate | 
 | signing subkey:: | 
 |  | 
 |     $ gpg --quick-addkey [fpr] ed25519 sign | 
 |  | 
 | Remember to tell the keyservers about this change, so others can pull down | 
 | your new subkey:: | 
 |  | 
 |     $ gpg --send-key [fpr] | 
 |  | 
 | .. note:: ECC support in GnuPG | 
 |  | 
 |     GnuPG 2.1 and later has full support for Elliptic Curve | 
 |     Cryptography, with ability to combine ECC subkeys with traditional | 
 |     RSA master keys. The main upside of ECC cryptography is that it is | 
 |     much faster computationally and creates much smaller signatures when | 
 |     compared byte for byte with 2048+ bit RSA keys. Unless you plan on | 
 |     using a smartcard device that does not support ECC operations, we | 
 |     recommend that you create an ECC signing subkey for your kernel | 
 |     work. | 
 |  | 
 |     If for some reason you prefer to stay with RSA subkeys, just replace | 
 |     "ed25519" with "rsa2048" in the above command. Additionally, if you | 
 |     plan to use a hardware device that does not support ED25519 ECC | 
 |     keys, like Nitrokey Pro or a Yubikey, then you should use | 
 |     "nistp256" instead or "ed25519." | 
 |  | 
 |  | 
 | Back up your master key for disaster recovery | 
 | --------------------------------------------- | 
 |  | 
 | The more signatures you have on your PGP key from other developers, the | 
 | more reasons you have to create a backup version that lives on something | 
 | other than digital media, for disaster recovery reasons. | 
 |  | 
 | The best way to create a printable hardcopy of your private key is by | 
 | using the ``paperkey`` software written for this very purpose. See ``man | 
 | paperkey`` for more details on the output format and its benefits over | 
 | other solutions. Paperkey should already be packaged for most | 
 | distributions. | 
 |  | 
 | Run the following command to create a hardcopy backup of your private | 
 | key:: | 
 |  | 
 |     $ gpg --export-secret-key [fpr] | paperkey -o /tmp/key-backup.txt | 
 |  | 
 | Print out that file (or pipe the output straight to lpr), then take a | 
 | pen and write your passphrase on the margin of the paper. **This is | 
 | strongly recommended** because the key printout is still encrypted with | 
 | that passphrase, and if you ever change it you will not remember what it | 
 | used to be when you had created the backup -- *guaranteed*. | 
 |  | 
 | Put the resulting printout and the hand-written passphrase into an envelope | 
 | and store in a secure and well-protected place, preferably away from your | 
 | home, such as your bank vault. | 
 |  | 
 | .. note:: | 
 |  | 
 |     Your printer is probably no longer a simple dumb device connected to | 
 |     your parallel port, but since the output is still encrypted with | 
 |     your passphrase, printing out even to "cloud-integrated" modern | 
 |     printers should remain a relatively safe operation. One option is to | 
 |     change the passphrase on your master key immediately after you are | 
 |     done with paperkey. | 
 |  | 
 | Back up your whole GnuPG directory | 
 | ---------------------------------- | 
 |  | 
 | .. warning:: | 
 |  | 
 |     **!!!Do not skip this step!!!** | 
 |  | 
 | It is important to have a readily available backup of your PGP keys | 
 | should you need to recover them. This is different from the | 
 | disaster-level preparedness we did with ``paperkey``. You will also rely | 
 | on these external copies whenever you need to use your Certify key -- | 
 | such as when making changes to your own key or signing other people's | 
 | keys after conferences and summits. | 
 |  | 
 | Start by getting a small USB "thumb" drive (preferably two!) that you | 
 | will use for backup purposes. You will need to encrypt them using LUKS | 
 | -- refer to your distro's documentation on how to accomplish this. | 
 |  | 
 | For the encryption passphrase, you can use the same one as on your | 
 | master key. | 
 |  | 
 | Once the encryption process is over, re-insert the USB drive and make | 
 | sure it gets properly mounted. Copy your entire ``.gnupg`` directory | 
 | over to the encrypted storage:: | 
 |  | 
 |     $ cp -a ~/.gnupg /media/disk/foo/gnupg-backup | 
 |  | 
 | You should now test to make sure everything still works:: | 
 |  | 
 |     $ gpg --homedir=/media/disk/foo/gnupg-backup --list-key [fpr] | 
 |  | 
 | If you don't get any errors, then you should be good to go. Unmount the | 
 | USB drive, distinctly label it so you don't blow it away next time you | 
 | need to use a random USB drive, and put in a safe place -- but not too | 
 | far away, because you'll need to use it every now and again for things | 
 | like editing identities, adding or revoking subkeys, or signing other | 
 | people's keys. | 
 |  | 
 | Remove the master key from  your homedir | 
 | ---------------------------------------- | 
 |  | 
 | The files in our home directory are not as well protected as we like to | 
 | think.  They can be leaked or stolen via many different means: | 
 |  | 
 | - by accident when making quick homedir copies to set up a new workstation | 
 | - by systems administrator negligence or malice | 
 | - via poorly secured backups | 
 | - via malware in desktop apps (browsers, pdf viewers, etc) | 
 | - via coercion when crossing international borders | 
 |  | 
 | Protecting your key with a good passphrase greatly helps reduce the risk | 
 | of any of the above, but passphrases can be discovered via keyloggers, | 
 | shoulder-surfing, or any number of other means. For this reason, the | 
 | recommended setup is to remove your master key from your home directory | 
 | and store it on offline storage. | 
 |  | 
 | .. warning:: | 
 |  | 
 |     Please see the previous section and make sure you have backed up | 
 |     your GnuPG directory in its entirety. What we are about to do will | 
 |     render your key useless if you do not have a usable backup! | 
 |  | 
 | First, identify the keygrip of your master key:: | 
 |  | 
 |     $ gpg --with-keygrip --list-key [fpr] | 
 |  | 
 | The output will be something like this:: | 
 |  | 
 |     pub   rsa2048 2018-01-24 [SC] [expires: 2020-01-24] | 
 |           000000000000000000000000AAAABBBBCCCCDDDD | 
 |           Keygrip = 1111000000000000000000000000000000000000 | 
 |     uid           [ultimate] Alice Dev <adev@kernel.org> | 
 |     sub   rsa2048 2018-01-24 [E] [expires: 2020-01-24] | 
 |           Keygrip = 2222000000000000000000000000000000000000 | 
 |     sub   ed25519 2018-01-24 [S] | 
 |           Keygrip = 3333000000000000000000000000000000000000 | 
 |  | 
 | Find the keygrip entry that is beneath the ``pub`` line (right under the | 
 | master key fingerprint). This will correspond directly to a file in your | 
 | ``~/.gnupg`` directory:: | 
 |  | 
 |     $ cd ~/.gnupg/private-keys-v1.d | 
 |     $ ls | 
 |     1111000000000000000000000000000000000000.key | 
 |     2222000000000000000000000000000000000000.key | 
 |     3333000000000000000000000000000000000000.key | 
 |  | 
 | All you have to do is simply remove the .key file that corresponds to | 
 | the master keygrip:: | 
 |  | 
 |     $ cd ~/.gnupg/private-keys-v1.d | 
 |     $ rm 1111000000000000000000000000000000000000.key | 
 |  | 
 | Now, if you issue the ``--list-secret-keys`` command, it will show that | 
 | the master key is missing (the ``#`` indicates it is not available):: | 
 |  | 
 |     $ gpg --list-secret-keys | 
 |     sec#  rsa2048 2018-01-24 [SC] [expires: 2020-01-24] | 
 |           000000000000000000000000AAAABBBBCCCCDDDD | 
 |     uid           [ultimate] Alice Dev <adev@kernel.org> | 
 |     ssb   rsa2048 2018-01-24 [E] [expires: 2020-01-24] | 
 |     ssb   ed25519 2018-01-24 [S] | 
 |  | 
 | You should also remove any ``secring.gpg`` files in the ``~/.gnupg`` | 
 | directory, which are left over from earlier versions of GnuPG. | 
 |  | 
 | If you don't have the "private-keys-v1.d" directory | 
 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
 |  | 
 | If you do not have a ``~/.gnupg/private-keys-v1.d`` directory, then your | 
 | secret keys are still stored in the legacy ``secring.gpg`` file used by | 
 | GnuPG v1. Making any changes to your key, such as changing the | 
 | passphrase or adding a subkey, should automatically convert the old | 
 | ``secring.gpg`` format to use ``private-keys-v1.d`` instead. | 
 |  | 
 | Once you get that done, make sure to delete the obsolete ``secring.gpg`` | 
 | file, which still contains your private keys. | 
 |  | 
 | .. _smartcards: | 
 |  | 
 | Move the subkeys to a dedicated crypto device | 
 | ============================================= | 
 |  | 
 | Even though the master key is now safe from being leaked or stolen, the | 
 | subkeys are still in your home directory. Anyone who manages to get | 
 | their hands on those will be able to decrypt your communication or fake | 
 | your signatures (if they know the passphrase). Furthermore, each time a | 
 | GnuPG operation is performed, the keys are loaded into system memory and | 
 | can be stolen from there by sufficiently advanced malware (think | 
 | Meltdown and Spectre). | 
 |  | 
 | The best way to completely protect your keys is to move them to a | 
 | specialized hardware device that is capable of smartcard operations. | 
 |  | 
 | The benefits of smartcards | 
 | -------------------------- | 
 |  | 
 | A smartcard contains a cryptographic chip that is capable of storing | 
 | private keys and performing crypto operations directly on the card | 
 | itself. Because the key contents never leave the smartcard, the | 
 | operating system of the computer into which you plug in the hardware | 
 | device is not able to retrieve the private keys themselves. This is very | 
 | different from the encrypted USB storage device we used earlier for | 
 | backup purposes -- while that USB device is plugged in and mounted, the | 
 | operating system is able to access the private key contents. | 
 |  | 
 | Using external encrypted USB media is not a substitute to having a | 
 | smartcard-capable device. | 
 |  | 
 | Available smartcard devices | 
 | --------------------------- | 
 |  | 
 | Unless all your laptops and workstations have smartcard readers, the | 
 | easiest is to get a specialized USB device that implements smartcard | 
 | functionality. There are several options available: | 
 |  | 
 | - `Nitrokey Start`_: Open hardware and Free Software, based on FSI | 
 |   Japan's `Gnuk`_. One of the few available commercial devices that | 
 |   support ED25519 ECC keys, but offer fewest security features (such as | 
 |   resistance to tampering or some side-channel attacks). | 
 | - `Nitrokey Pro 2`_: Similar to the Nitrokey Start, but more | 
 |   tamper-resistant and offers more security features. Pro 2 supports ECC | 
 |   cryptography (NISTP). | 
 | - `Yubikey 5`_: proprietary hardware and software, but cheaper than | 
 |   Nitrokey Pro and comes available in the USB-C form that is more useful | 
 |   with newer laptops. Offers additional security features such as FIDO | 
 |   U2F, among others, and now finally supports ECC keys (NISTP). | 
 |  | 
 | `LWN has a good review`_ of some of the above models, as well as several | 
 | others. Your choice will depend on cost, shipping availability in your | 
 | geographical region, and open/proprietary hardware considerations. | 
 |  | 
 | .. note:: | 
 |  | 
 |     If you are listed in MAINTAINERS or have an account at kernel.org, | 
 |     you `qualify for a free Nitrokey Start`_ courtesy of The Linux | 
 |     Foundation. | 
 |  | 
 | .. _`Nitrokey Start`: https://shop.nitrokey.com/shop/product/nitrokey-start-6 | 
 | .. _`Nitrokey Pro 2`: https://shop.nitrokey.com/shop/product/nitrokey-pro-2-3 | 
 | .. _`Yubikey 5`: https://www.yubico.com/products/yubikey-5-overview/ | 
 | .. _Gnuk: https://www.fsij.org/doc-gnuk/ | 
 | .. _`LWN has a good review`: https://lwn.net/Articles/736231/ | 
 | .. _`qualify for a free Nitrokey Start`: https://www.kernel.org/nitrokey-digital-tokens-for-kernel-developers.html | 
 |  | 
 | Configure your smartcard device | 
 | ------------------------------- | 
 |  | 
 | Your smartcard device should Just Work (TM) the moment you plug it into | 
 | any modern Linux workstation. You can verify it by running:: | 
 |  | 
 |     $ gpg --card-status | 
 |  | 
 | If you see full smartcard details, then you are good to go. | 
 | Unfortunately, troubleshooting all possible reasons why things may not | 
 | be working for you is way beyond the scope of this guide. If you are | 
 | having trouble getting the card to work with GnuPG, please seek help via | 
 | usual support channels. | 
 |  | 
 | To configure your smartcard, you will need to use the GnuPG menu system, as | 
 | there are no convenient command-line switches:: | 
 |  | 
 |     $ gpg --card-edit | 
 |     [...omitted...] | 
 |     gpg/card> admin | 
 |     Admin commands are allowed | 
 |     gpg/card> passwd | 
 |  | 
 | You should set the user PIN (1), Admin PIN (3), and the Reset Code (4). | 
 | Please make sure to record and store these in a safe place -- especially | 
 | the Admin PIN and the Reset Code (which allows you to completely wipe | 
 | the smartcard). You so rarely need to use the Admin PIN, that you will | 
 | inevitably forget what it is if you do not record it. | 
 |  | 
 | Getting back to the main card menu, you can also set other values (such | 
 | as name, sex, login data, etc), but it's not necessary and will | 
 | additionally leak information about your smartcard should you lose it. | 
 |  | 
 | .. note:: | 
 |  | 
 |     Despite having the name "PIN", neither the user PIN nor the admin | 
 |     PIN on the card need to be numbers. | 
 |  | 
 | .. warning:: | 
 |  | 
 |     Some devices may require that you move the subkeys onto the device | 
 |     before you can change the passphrase. Please check the documentation | 
 |     provided by the device manufacturer. | 
 |  | 
 | Move the subkeys to your smartcard | 
 | ---------------------------------- | 
 |  | 
 | Exit the card menu (using "q") and save all changes. Next, let's move | 
 | your subkeys onto the smartcard. You will need both your PGP key | 
 | passphrase and the admin PIN of the card for most operations:: | 
 |  | 
 |     $ gpg --edit-key [fpr] | 
 |  | 
 |     Secret subkeys are available. | 
 |  | 
 |     pub  rsa2048/AAAABBBBCCCCDDDD | 
 |          created: 2018-01-23  expires: 2020-01-23  usage: SC | 
 |          trust: ultimate      validity: ultimate | 
 |     ssb  rsa2048/1111222233334444 | 
 |          created: 2018-01-23  expires: never       usage: E | 
 |     ssb  ed25519/5555666677778888 | 
 |          created: 2017-12-07  expires: never       usage: S | 
 |     [ultimate] (1). Alice Dev <adev@kernel.org> | 
 |  | 
 |     gpg> | 
 |  | 
 | Using ``--edit-key`` puts us into the menu mode again, and you will | 
 | notice that the key listing is a little different. From here on, all | 
 | commands are done from inside this menu mode, as indicated by ``gpg>``. | 
 |  | 
 | First, let's select the key we'll be putting onto the card -- you do | 
 | this by typing ``key 1`` (it's the first one in the listing, the **[E]** | 
 | subkey):: | 
 |  | 
 |     gpg> key 1 | 
 |  | 
 | In the output, you should now see ``ssb*`` on the **[E]** key. The ``*`` | 
 | indicates which key is currently "selected." It works as a *toggle*, | 
 | meaning that if you type ``key 1`` again, the ``*`` will disappear and | 
 | the key will not be selected any more. | 
 |  | 
 | Now, let's move that key onto the smartcard:: | 
 |  | 
 |     gpg> keytocard | 
 |     Please select where to store the key: | 
 |        (2) Encryption key | 
 |     Your selection? 2 | 
 |  | 
 | Since it's our **[E]** key, it makes sense to put it into the Encryption | 
 | slot.  When you submit your selection, you will be prompted first for | 
 | your PGP key passphrase, and then for the admin PIN. If the command | 
 | returns without an error, your key has been moved. | 
 |  | 
 | **Important**: Now type ``key 1`` again to unselect the first key, and | 
 | ``key 2`` to select the **[S]** key:: | 
 |  | 
 |     gpg> key 1 | 
 |     gpg> key 2 | 
 |     gpg> keytocard | 
 |     Please select where to store the key: | 
 |        (1) Signature key | 
 |        (3) Authentication key | 
 |     Your selection? 1 | 
 |  | 
 | You can use the **[S]** key both for Signature and Authentication, but | 
 | we want to make sure it's in the Signature slot, so choose (1). Once | 
 | again, if your command returns without an error, then the operation was | 
 | successful:: | 
 |  | 
 |     gpg> q | 
 |     Save changes? (y/N) y | 
 |  | 
 | Saving the changes will delete the keys you moved to the card from your | 
 | home directory (but it's okay, because we have them in our backups | 
 | should we need to do this again for a replacement smartcard). | 
 |  | 
 | Verifying that the keys were moved | 
 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
 |  | 
 | If you perform ``--list-secret-keys`` now, you will see a subtle | 
 | difference in the output:: | 
 |  | 
 |     $ gpg --list-secret-keys | 
 |     sec#  rsa2048 2018-01-24 [SC] [expires: 2020-01-24] | 
 |           000000000000000000000000AAAABBBBCCCCDDDD | 
 |     uid           [ultimate] Alice Dev <adev@kernel.org> | 
 |     ssb>  rsa2048 2018-01-24 [E] [expires: 2020-01-24] | 
 |     ssb>  ed25519 2018-01-24 [S] | 
 |  | 
 | The ``>`` in the ``ssb>`` output indicates that the subkey is only | 
 | available on the smartcard. If you go back into your secret keys | 
 | directory and look at the contents there, you will notice that the | 
 | ``.key`` files there have been replaced with stubs:: | 
 |  | 
 |     $ cd ~/.gnupg/private-keys-v1.d | 
 |     $ strings *.key | grep 'private-key' | 
 |  | 
 | The output should contain ``shadowed-private-key`` to indicate that | 
 | these files are only stubs and the actual content is on the smartcard. | 
 |  | 
 | Verifying that the smartcard is functioning | 
 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
 |  | 
 | To verify that the smartcard is working as intended, you can create a | 
 | signature:: | 
 |  | 
 |     $ echo "Hello world" | gpg --clearsign > /tmp/test.asc | 
 |     $ gpg --verify /tmp/test.asc | 
 |  | 
 | This should ask for your smartcard PIN on your first command, and then | 
 | show "Good signature" after you run ``gpg --verify``. | 
 |  | 
 | Congratulations, you have successfully made it extremely difficult to | 
 | steal your digital developer identity! | 
 |  | 
 | Other common GnuPG operations | 
 | ----------------------------- | 
 |  | 
 | Here is a quick reference for some common operations you'll need to do | 
 | with your PGP key. | 
 |  | 
 | Mounting your master key offline storage | 
 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
 |  | 
 | You will need your master key for any of the operations below, so you | 
 | will first need to mount your backup offline storage and tell GnuPG to | 
 | use it:: | 
 |  | 
 |     $ export GNUPGHOME=/media/disk/foo/gnupg-backup | 
 |     $ gpg --list-secret-keys | 
 |  | 
 | You want to make sure that you see ``sec`` and not ``sec#`` in the | 
 | output (the ``#`` means the key is not available and you're still using | 
 | your regular home directory location). | 
 |  | 
 | Extending key expiration date | 
 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
 |  | 
 | The master key has the default expiration date of 2 years from the date | 
 | of creation. This is done both for security reasons and to make obsolete | 
 | keys eventually disappear from keyservers. | 
 |  | 
 | To extend the expiration on your key by a year from current date, just | 
 | run:: | 
 |  | 
 |     $ gpg --quick-set-expire [fpr] 1y | 
 |  | 
 | You can also use a specific date if that is easier to remember (e.g. | 
 | your birthday, January 1st, or Canada Day):: | 
 |  | 
 |     $ gpg --quick-set-expire [fpr] 2020-07-01 | 
 |  | 
 | Remember to send the updated key back to keyservers:: | 
 |  | 
 |     $ gpg --send-key [fpr] | 
 |  | 
 | Updating your work directory after any changes | 
 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
 |  | 
 | After you make any changes to your key using the offline storage, you will | 
 | want to import these changes back into your regular working directory:: | 
 |  | 
 |     $ gpg --export | gpg --homedir ~/.gnupg --import | 
 |     $ unset GNUPGHOME | 
 |  | 
 | Using gpg-agent over ssh | 
 | ~~~~~~~~~~~~~~~~~~~~~~~~ | 
 |  | 
 | You can forward your gpg-agent over ssh if you need to sign tags or | 
 | commits on a remote system. Please refer to the instructions provided | 
 | on the GnuPG wiki: | 
 |  | 
 | - `Agent Forwarding over SSH`_ | 
 |  | 
 | It works more smoothly if you can modify the sshd server settings on the | 
 | remote end. | 
 |  | 
 | .. _`Agent Forwarding over SSH`: https://wiki.gnupg.org/AgentForwarding | 
 |  | 
 |  | 
 | Using PGP with Git | 
 | ================== | 
 |  | 
 | One of the core features of Git is its decentralized nature -- once a | 
 | repository is cloned to your system, you have full history of the | 
 | project, including all of its tags, commits and branches. However, with | 
 | hundreds of cloned repositories floating around, how does anyone verify | 
 | that their copy of linux.git has not been tampered with by a malicious | 
 | third party? | 
 |  | 
 | Or what happens if a backdoor is discovered in the code and the "Author" | 
 | line in the commit says it was done by you, while you're pretty sure you | 
 | had `nothing to do with it`_? | 
 |  | 
 | To address both of these issues, Git introduced PGP integration. Signed | 
 | tags prove the repository integrity by assuring that its contents are | 
 | exactly the same as on the workstation of the developer who created the | 
 | tag, while signed commits make it nearly impossible for someone to | 
 | impersonate you without having access to your PGP keys. | 
 |  | 
 | .. _`nothing to do with it`: https://github.com/jayphelps/git-blame-someone-else | 
 |  | 
 | Configure git to use your PGP key | 
 | --------------------------------- | 
 |  | 
 | If you only have one secret key in your keyring, then you don't really | 
 | need to do anything extra, as it becomes your default key.  However, if | 
 | you happen to have multiple secret keys, you can tell git which key | 
 | should be used (``[fpr]`` is the fingerprint of your key):: | 
 |  | 
 |     $ git config --global user.signingKey [fpr] | 
 |  | 
 | **IMPORTANT**: If you have a distinct ``gpg2`` command, then you should | 
 | tell git to always use it instead of the legacy ``gpg`` from version 1:: | 
 |  | 
 |     $ git config --global gpg.program gpg2 | 
 |     $ git config --global gpgv.program gpgv2 | 
 |  | 
 | How to work with signed tags | 
 | ---------------------------- | 
 |  | 
 | To create a signed tag, simply pass the ``-s`` switch to the tag | 
 | command:: | 
 |  | 
 |     $ git tag -s [tagname] | 
 |  | 
 | Our recommendation is to always sign git tags, as this allows other | 
 | developers to ensure that the git repository they are pulling from has | 
 | not been maliciously altered. | 
 |  | 
 | How to verify signed tags | 
 | ~~~~~~~~~~~~~~~~~~~~~~~~~ | 
 |  | 
 | To verify a signed tag, simply use the ``verify-tag`` command:: | 
 |  | 
 |     $ git verify-tag [tagname] | 
 |  | 
 | If you are pulling a tag from another fork of the project repository, | 
 | git should automatically verify the signature at the tip you're pulling | 
 | and show you the results during the merge operation:: | 
 |  | 
 |     $ git pull [url] tags/sometag | 
 |  | 
 | The merge message will contain something like this:: | 
 |  | 
 |     Merge tag 'sometag' of [url] | 
 |  | 
 |     [Tag message] | 
 |  | 
 |     # gpg: Signature made [...] | 
 |     # gpg: Good signature from [...] | 
 |  | 
 | If you are verifying someone else's git tag, then you will need to | 
 | import their PGP key. Please refer to the | 
 | ":ref:`verify_identities`" section below. | 
 |  | 
 | .. note:: | 
 |  | 
 |     If you get "``gpg: Can't check signature: unknown pubkey | 
 |     algorithm``" error, you need to tell git to use gpgv2 for | 
 |     verification, so it properly processes signatures made by ECC keys. | 
 |     See instructions at the start of this section. | 
 |  | 
 | Configure git to always sign annotated tags | 
 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
 |  | 
 | Chances are, if you're creating an annotated tag, you'll want to sign | 
 | it. To force git to always sign annotated tags, you can set a global | 
 | configuration option:: | 
 |  | 
 |     $ git config --global tag.forceSignAnnotated true | 
 |  | 
 | How to work with signed commits | 
 | ------------------------------- | 
 |  | 
 | It is easy to create signed commits, but it is much more difficult to | 
 | use them in Linux kernel development, since it relies on patches sent to | 
 | the mailing list, and this workflow does not preserve PGP commit | 
 | signatures. Furthermore, when rebasing your repository to match | 
 | upstream, even your own PGP commit signatures will end up discarded. For | 
 | this reason, most kernel developers don't bother signing their commits | 
 | and will ignore signed commits in any external repositories that they | 
 | rely upon in their work. | 
 |  | 
 | However, if you have your working git tree publicly available at some | 
 | git hosting service (kernel.org, infradead.org, ozlabs.org, or others), | 
 | then the recommendation is that you sign all your git commits even if | 
 | upstream developers do not directly benefit from this practice. | 
 |  | 
 | We recommend this for the following reasons: | 
 |  | 
 | 1. Should there ever be a need to perform code forensics or track code | 
 |    provenance, even externally maintained trees carrying PGP commit | 
 |    signatures will be valuable for such purposes. | 
 | 2. If you ever need to re-clone your local repository (for example, | 
 |    after a disk failure), this lets you easily verify the repository | 
 |    integrity before resuming your work. | 
 | 3. If someone needs to cherry-pick your commits, this allows them to | 
 |    quickly verify their integrity before applying them. | 
 |  | 
 | Creating signed commits | 
 | ~~~~~~~~~~~~~~~~~~~~~~~ | 
 |  | 
 | To create a signed commit, you just need to pass the ``-S`` flag to the | 
 | ``git commit`` command (it's capital ``-S`` due to collision with | 
 | another flag):: | 
 |  | 
 |     $ git commit -S | 
 |  | 
 | Configure git to always sign commits | 
 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
 |  | 
 | You can tell git to always sign commits:: | 
 |  | 
 |     git config --global commit.gpgSign true | 
 |  | 
 | .. note:: | 
 |  | 
 |     Make sure you configure ``gpg-agent`` before you turn this on. | 
 |  | 
 | .. _verify_identities: | 
 |  | 
 | How to verify kernel developer identities | 
 | ========================================= | 
 |  | 
 | Signing tags and commits is easy, but how does one go about verifying | 
 | that the key used to sign something belongs to the actual kernel | 
 | developer and not to a malicious imposter? | 
 |  | 
 | Configure auto-key-retrieval using WKD and DANE | 
 | ----------------------------------------------- | 
 |  | 
 | If you are not already someone with an extensive collection of other | 
 | developers' public keys, then you can jumpstart your keyring by relying | 
 | on key auto-discovery and auto-retrieval. GnuPG can piggyback on other | 
 | delegated trust technologies, namely DNSSEC and TLS, to get you going if | 
 | the prospect of starting your own Web of Trust from scratch is too | 
 | daunting. | 
 |  | 
 | Add the following to your ``~/.gnupg/gpg.conf``:: | 
 |  | 
 |     auto-key-locate wkd,dane,local | 
 |     auto-key-retrieve | 
 |  | 
 | DNS-Based Authentication of Named Entities ("DANE") is a method for | 
 | publishing public keys in DNS and securing them using DNSSEC signed | 
 | zones. Web Key Directory ("WKD") is the alternative method that uses | 
 | https lookups for the same purpose. When using either DANE or WKD for | 
 | looking up public keys, GnuPG will validate DNSSEC or TLS certificates, | 
 | respectively, before adding auto-retrieved public keys to your local | 
 | keyring. | 
 |  | 
 | Kernel.org publishes the WKD for all developers who have kernel.org | 
 | accounts. Once you have the above changes in your ``gpg.conf``, you can | 
 | auto-retrieve the keys for Linus Torvalds and Greg Kroah-Hartman (if you | 
 | don't already have them):: | 
 |  | 
 |     $ gpg --locate-keys torvalds@kernel.org gregkh@kernel.org | 
 |  | 
 | If you have a kernel.org account, then you should `add the kernel.org | 
 | UID to your key`_ to make WKD more useful to other kernel developers. | 
 |  | 
 | .. _`add the kernel.org UID to your key`: https://korg.wiki.kernel.org/userdoc/mail#adding_a_kernelorg_uid_to_your_pgp_key | 
 |  | 
 | Web of Trust (WOT) vs. Trust on First Use (TOFU) | 
 | ------------------------------------------------ | 
 |  | 
 | PGP incorporates a trust delegation mechanism known as the "Web of | 
 | Trust." At its core, this is an attempt to replace the need for | 
 | centralized Certification Authorities of the HTTPS/TLS world. Instead of | 
 | various software makers dictating who should be your trusted certifying | 
 | entity, PGP leaves this responsibility to each user. | 
 |  | 
 | Unfortunately, very few people understand how the Web of Trust works. | 
 | While it remains an important aspect of the OpenPGP specification, | 
 | recent versions of GnuPG (2.2 and above) have implemented an alternative | 
 | mechanism called "Trust on First Use" (TOFU). You can think of TOFU as | 
 | "the SSH-like approach to trust." With SSH, the first time you connect | 
 | to a remote system, its key fingerprint is recorded and remembered. If | 
 | the key changes in the future, the SSH client will alert you and refuse | 
 | to connect, forcing you to make a decision on whether you choose to | 
 | trust the changed key or not. Similarly, the first time you import | 
 | someone's PGP key, it is assumed to be valid. If at any point in the | 
 | future GnuPG comes across another key with the same identity, both the | 
 | previously imported key and the new key will be marked as invalid and | 
 | you will need to manually figure out which one to keep. | 
 |  | 
 | We recommend that you use the combined TOFU+PGP trust model (which is | 
 | the new default in GnuPG v2). To set it, add (or modify) the | 
 | ``trust-model`` setting in ``~/.gnupg/gpg.conf``:: | 
 |  | 
 |     trust-model tofu+pgp | 
 |  | 
 | How to use keyservers (more) safely | 
 | ----------------------------------- | 
 |  | 
 | If you get a "No public key" error when trying to validate someone's | 
 | tag, then you should attempt to lookup that key using a keyserver. It is | 
 | important to keep in mind that there is absolutely no guarantee that the | 
 | key you retrieve from PGP keyservers belongs to the actual person -- | 
 | that much is by design. You are supposed to use the Web of Trust to | 
 | establish key validity. | 
 |  | 
 | How to properly maintain the Web of Trust is beyond the scope of this | 
 | document, simply because doing it properly requires both effort and | 
 | dedication that tends to be beyond the caring threshold of most human | 
 | beings. Here are some shortcuts that will help you reduce the risk of | 
 | importing a malicious key. | 
 |  | 
 | First, let's say you've tried to run ``git verify-tag`` but it returned | 
 | an error saying the key is not found:: | 
 |  | 
 |     $ git verify-tag sunxi-fixes-for-4.15-2 | 
 |     gpg: Signature made Sun 07 Jan 2018 10:51:55 PM EST | 
 |     gpg:                using RSA key DA73759BF8619E484E5A3B47389A54219C0F2430 | 
 |     gpg:                issuer "wens@...org" | 
 |     gpg: Can't check signature: No public key | 
 |  | 
 | Let's query the keyserver for more info about that key fingerprint (the | 
 | fingerprint probably belongs to a subkey, so we can't use it directly | 
 | without finding out the ID of the master key it is associated with):: | 
 |  | 
 |     $ gpg --search DA73759BF8619E484E5A3B47389A54219C0F2430 | 
 |     gpg: data source: hkp://keys.gnupg.net | 
 |     (1) Chen-Yu Tsai <wens@...org> | 
 |           4096 bit RSA key C94035C21B4F2AEB, created: 2017-03-14, expires: 2019-03-15 | 
 |     Keys 1-1 of 1 for "DA73759BF8619E484E5A3B47389A54219C0F2430".  Enter number(s), N)ext, or Q)uit > q | 
 |  | 
 | Locate the ID of the master key in the output, in our example | 
 | ``C94035C21B4F2AEB``. Now display the key of Linus Torvalds that you | 
 | have on your keyring:: | 
 |  | 
 |     $ gpg --list-key torvalds@kernel.org | 
 |     pub   rsa2048 2011-09-20 [SC] | 
 |           ABAF11C65A2970B130ABE3C479BE3E4300411886 | 
 |     uid           [ unknown] Linus Torvalds <torvalds@kernel.org> | 
 |     sub   rsa2048 2011-09-20 [E] | 
 |  | 
 | Next, find a trust path from Linus Torvalds to the key-id you found via ``gpg | 
 | --search`` of the unknown key.  For this, you can use several tools including | 
 | https://github.com/mricon/wotmate, | 
 | https://git.kernel.org/pub/scm/docs/kernel/pgpkeys.git/tree/graphs, and | 
 | https://the.earth.li/~noodles/pathfind.html. | 
 |  | 
 | If you get a few decent trust paths, then it's a pretty good indication | 
 | that it is a valid key. You can add it to your keyring from the | 
 | keyserver now:: | 
 |  | 
 |     $ gpg --recv-key C94035C21B4F2AEB | 
 |  | 
 | This process is not perfect, and you are obviously trusting the | 
 | administrators of the PGP Pathfinder service to not be malicious (in | 
 | fact, this goes against :ref:`devs_not_infra`). However, if you | 
 | do not carefully maintain your own web of trust, then it is a marked | 
 | improvement over blindly trusting keyservers. |