summaryrefslogtreecommitdiffstats
path: root/Documentation/process/maintainer-pgp-guide.rst
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-08-30 09:22:00 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-08-30 09:22:00 -0700
commit034dd340b08be1f2f0477ad16131d609f9dbd53c (patch)
tree2536f4b2d7893ccd916b5abdf3c454ad6edc03c2 /Documentation/process/maintainer-pgp-guide.rst
downloadlinux-stable-034dd340b08be1f2f0477ad16131d609f9dbd53c.tar.gz
linux-stable-034dd340b08be1f2f0477ad16131d609f9dbd53c.zip
Merge tag 'trace-v7.3-2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-tracegrafted
Pull tracing fixes from Steven Rostedt: - Fix error output of boot instance creation failure Currently if a boot instance creation fails, instead of printing out the name of the instance that failed, it prints "(null)". That is because it prints "cur_str" that had already been processed by strsep(). Print the saved name instead. While at it, print the error code of the failure. - Fix use-after-free for same named historgrams Histograms can be named so that they can be used in multiple events. But if the named histogram has a variable attached, the second event that uses the named histogram which duplicates it and needs to free the original after duplication leaves the old variable in place and still visible. If another histogram uses than variable, it will use the stale one which will try to reference the freed duplicate histogram and crash the kernel. Free the duplicate variables along with the duplicated histogram data. - Check return value of kthread_run() in event self test The events self tests uses a kthread for testing but does not check if it succeeded in creating a kthread. If the kthread creation were to fail, the code will still try to call kthread_stop() on the error returned. - Fix race between reading trace_pipe and updating subbuffer size If a user is reading the trace_pipe file at the same time they update the ring buffer sub-buffer size, can cause the trace_pipe read to read stale data. Add trace_access_lock() around updating the ring buffer sub-buffer size. - Fix eventfs_inode on failure path in creation of the events directory In the creation of the "events" directory, if after allocating the eventfs_inode a failure is detected, it calls cleanup_ei() which calls free_ei(). The free_ei() will test if eventfs_inode being freed has no children. It is a bug if it does. But on the failure case of the creation of the "events" directory, the children lists have not yet been initialized and the free will trigger a warning because list_empty() on an uninitialized list returns false. Move the initialization into init_ei() where it makes more sense and makes sure that a created eventfs_inode has its lists initialized upon creation. - Check return value of kthread_run() in ftrace direct sample code The sample code that shows how to use the ftrace direct calls does not test the return of kthread_run() to see if it succeeds. Return a failure if the kthread_run() doesn't succeed. - Clear user events state on fork in case of alloc failure On fork, the child gets a pointer to the parent's user events state. It makes a copy of it then updates the child's pointer to it. But if the allocation fails, the duplication function leaves the child with a pointer to its parent's descriptor. When the child cleans up its data, it will free the parent's descriptor while the parent is still using it. In the duplication function, set the child's user_event_mm to NULL before testing if the allocation succeeded, and when it exits it will not free the parent's descriptor. - Fix retry exhaustion in simple ring buffer reader swap simple_ring_buffer_swap_reader_page() starts with retry set to 8 and post-decrements it only after a failed link replacement. On the final attempt, a successful replacement leaves retry at zero, while a failed replacement leaves it at -1. But the check for success expects the retry value to be non-zero and exits with an error on zero. This is the opposite result. Fix it. - Fail nicely when the remote swap_reader_page() returns an error Currently, if the swap_reader_page() of a remote buffer fails, it triggers a WARN_ON_ONCE() and continues normally. Instead, have it exit with an error and a pr_warn() print instead of a full WARNING. * tag 'trace-v7.3-2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: ring-buffer: Stop remote reader update when page swap fails tracing: Fix retry exhaustion in simple ring buffer reader swap tracing/user_events: Clear copied tracing state before fork duplication samples/ftrace: Fix kthread_stop() on ERR_PTR in ftrace-direct-multi-modify samples/ftrace: Fix kthread_stop() on ERR_PTR in ftrace-direct-modify eventfs: Initialize ei->children and ei->list in init_ei() tracing: Fix use-after-free in trace_pipe read on sub-buffer order change tracing: Fix crash passing ERR_PTR to kthread_stop() tracing: Fix use-after-free with same-name named triggers tracing: Fix logged instance name on creation failure
Diffstat (limited to 'Documentation/process/maintainer-pgp-guide.rst')
-rw-r--r--Documentation/process/maintainer-pgp-guide.rst915
1 files changed, 915 insertions, 0 deletions
diff --git a/Documentation/process/maintainer-pgp-guide.rst b/Documentation/process/maintainer-pgp-guide.rst
new file mode 100644
index 000000000..652dfbe64
--- /dev/null
+++ b/Documentation/process/maintainer-pgp-guide.rst
@@ -0,0 +1,915 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _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 merely
+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 2.4 or later
+----------------------
+
+Your distro should already have GnuPG installed by default, you just
+need to verify that you are using a reasonably recent version of it.
+To check, run::
+
+ $ gpg --version | head -n1
+
+If you have version 2.4 or above, then you are good to go. If you have
+an earlier version, then you are using a release of GnuPG that is no
+longer maintained and some commands from this guide may not work.
+
+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.
+
+.. _protect_your_key:
+
+Protect your 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).
+
+Understanding PGP Subkeys
+-------------------------
+
+A PGP key rarely consists of a single keypair -- usually it is a
+collection of independent subkeys that can be used for different
+purposes based on their capabilities, assigned at their creation time.
+PGP defines four capabilities that a key can have:
+
+- **[S]** keys can be used for signing
+- **[E]** keys can be used for encryption
+- **[A]** keys can be used for authentication
+- **[C]** keys can be used for certifying other keys
+
+The key with the **[C]** capability is often called the "master" key,
+but this terminology is misleading because it implies that the Certify
+key can be used in place of any of other subkey on the same chain (like
+a physical "master key" can be used to open locks made for other keys).
+Since this is not the case, this guide will refer to it as "the Certify
+key" to avoid any ambiguity.
+
+It is critical to fully understand the following:
+
+1. All subkeys are fully independent from each other. If you lose a
+ private subkey, it cannot be restored or recreated from any other
+ private key on your chain.
+2. With the exception of the Certify key, there can be multiple subkeys
+ with identical capabilities (e.g. you can have 2 valid encryption
+ subkeys, 3 valid signing subkeys, but only one valid certification
+ subkey). All subkeys are fully independent -- a message encrypted to
+ one **[E]** subkey cannot be decrypted with any other **[E]** subkey
+ you may also have.
+3. A single subkey may have multiple capabilities (e.g. your **[C]** key
+ can also be your **[S]** key).
+
+The key carrying the **[C]** (certify) capability 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:
+
+- One subkey 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 ed25519 2022-12-20 [SC] [expires: 2024-12-19]
+ 000000000000000000000000AAAABBBBCCCCDDDD
+ uid [ultimate] Alice Dev <adev@kernel.org>
+ ssb cv25519 2022-12-20 [E] [expires: 2024-12-19]
+
+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 Certify 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
+
+Back up your Certify 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.
+
+A good 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, 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::
+
+ The key is still encrypted with your passphrase, so printing out
+ even to "cloud-integrated" modern printers should remain a
+ relatively safe operation.
+
+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 an external media card (preferably two!) that you will
+use for backup purposes. You will need to create an encrypted partition
+on this device 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
+PGP key.
+
+Once the encryption process is over, re-insert your device 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
+device, distinctly label it so you don't overwrite it by accident, 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 Certify 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 Certify 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 Certify key::
+
+ $ gpg --with-keygrip --list-key [fpr]
+
+The output will be something like this::
+
+ pub ed25519 2022-12-20 [SC] [expires: 2022-12-19]
+ 000000000000000000000000AAAABBBBCCCCDDDD
+ Keygrip = 1111000000000000000000000000000000000000
+ uid [ultimate] Alice Dev <adev@kernel.org>
+ sub cv25519 2022-12-20 [E] [expires: 2022-12-19]
+ Keygrip = 2222000000000000000000000000000000000000
+ sub ed25519 2022-12-20 [S]
+ Keygrip = 3333000000000000000000000000000000000000
+
+Find the keygrip entry that is beneath the ``pub`` line (right under the
+Certify 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
+
+It is sufficient to remove the .key file that corresponds to the Certify
+key keygrip::
+
+ $ cd ~/.gnupg/private-keys-v1.d
+ $ rm 1111000000000000000000000000000000000000.key
+
+Now, if you issue the ``--list-secret-keys`` command, it will show that
+the Certify key is missing (the ``#`` indicates it is not available)::
+
+ $ gpg --list-secret-keys
+ sec# ed25519 2022-12-20 [SC] [expires: 2024-12-19]
+ 000000000000000000000000AAAABBBBCCCCDDDD
+ uid [ultimate] Alice Dev <adev@kernel.org>
+ ssb cv25519 2022-12-20 [E] [expires: 2024-12-19]
+ ssb ed25519 2022-12-20 [S]
+
+You should also remove any ``secring.gpg`` files in the ``~/.gnupg``
+directory, which may be left over from previous 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 Certify 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).
+
+A good 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 media storage device we used earlier for
+backup purposes -- while that device is plugged in and mounted, the
+operating system is able to access the private key contents.
+
+Using external encrypted 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 cheapest options, but offers fewest
+ security features (such as resistance to tampering or some
+ side-channel attacks).
+- `Nitrokey 3`_: Similar to the Nitrokey Start, but more
+ tamper-resistant and offers more security features and USB
+ form-factors. Supports ECC cryptography (ED25519 and NISTP).
+- `Yubikey 5`_: proprietary hardware and software, but cheaper than
+ Nitrokey with a similar set of features. Supports ECC cryptography
+ (ED25519 and NISTP).
+
+Your choice will depend on cost, shipping availability in your
+geographical region, and open/proprietary hardware considerations.
+
+.. note::
+
+ If you are listed in an `M:` entry in MAINTAINERS or have an account at
+ kernel.org, you `qualify for a free Nitrokey Start`_ courtesy of The Linux
+ Foundation.
+
+.. _`Nitrokey Start`: https://www.nitrokey.com/products/nitrokeys
+.. _`Nitrokey 3`: https://www.nitrokey.com/products/nitrokeys
+.. _`Yubikey 5`: https://www.yubico.com/products/yubikey-5-overview/
+.. _Gnuk: https://www.fsij.org/doc-gnuk/
+.. _`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, gender, 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 ed25519/AAAABBBBCCCCDDDD
+ created: 2022-12-20 expires: 2024-12-19 usage: SC
+ trust: ultimate validity: ultimate
+ ssb cv25519/1111222233334444
+ created: 2022-12-20 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# ed25519 2022-12-20 [SC] [expires: 2024-12-19]
+ 000000000000000000000000AAAABBBBCCCCDDDD
+ uid [ultimate] Alice Dev <adev@kernel.org>
+ ssb> cv25519 2022-12-20 [E] [expires: 2024-12-19]
+ ssb> ed25519 2022-12-20 [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 safe offline storage
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You will need your Certify 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 Certify 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] 2038-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
+
+.. _pgp_with_git:
+
+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 malicious code is discovered in the kernel 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]
+
+How to work with signed tags
+----------------------------
+
+To create a signed tag, 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, 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, you will first need to
+import their PGP key. Please refer to the ":ref:`verify_identities`"
+section below.
+
+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 also possible to create signed commits, but they have limited
+usefulness in Linux kernel development. The kernel contribution workflow
+relies on sending in patches, and converting commits to patches does not
+preserve git commit signatures. Furthermore, when rebasing your own
+repository on a newer upstream, 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.
+
+That said, 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 reinstalling your system), this lets you 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, 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 work with signed patches
+-------------------------------
+
+It is possible to use your PGP key to sign patches sent to kernel
+developer mailing lists. Since existing email signature mechanisms
+(PGP-Mime or PGP-inline) tend to cause problems with regular code
+review tasks, you should use the tool kernel.org created for this
+purpose that puts cryptographic attestation signatures into message
+headers (a-la DKIM):
+
+- `Patatt Patch Attestation`_
+
+.. _`Patatt Patch Attestation`: https://pypi.org/project/patatt/
+
+Installing and configuring patatt
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. note::
+
+ If you use B4 to send in your patches, patatt is already installed
+ and integrated into your workflow.
+
+Patatt is packaged for many distributions already, so please check there
+first. You can also install it from pypi using "``pip install patatt``".
+
+If you already have your PGP key configured with git (via the
+``user.signingKey`` configuration parameter), then patatt requires no
+further configuration. You can start signing your patches by installing
+the git-send-email hook in the repository you want::
+
+ patatt install-hook
+
+Now any patches you send with ``git send-email`` will be automatically
+signed with your cryptographic signature.
+
+Checking patatt signatures
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you are using ``b4`` to retrieve and apply patches, then it will
+automatically attempt to verify all DKIM and patatt signatures it
+encounters, for example::
+
+ $ b4 am 20220720205013.890942-1-broonie@kernel.org
+ [...]
+ Checking attestation on all messages, may take a moment...
+ ---
+ ✓ [PATCH v1 1/3] kselftest/arm64: Correct buffer allocation for SVE Z registers
+ ✓ [PATCH v1 2/3] arm64/sve: Document our actual ABI for clearing registers on syscall
+ ✓ [PATCH v1 3/3] kselftest/arm64: Enforce actual ABI for SVE syscalls
+ ---
+ ✓ Signed: openpgp/broonie@kernel.org
+ ✓ Signed: DKIM/kernel.org
+
+.. note::
+
+ Patatt and b4 are still in active development and you should check
+ the latest documentation for these projects for any new or updated
+ features.
+
+.. _kernel_identities:
+
+How to verify kernel developer identities
+=========================================
+
+Signing tags and commits is straightforward, 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.docs.kernel.org/mail.html#adding-a-kernel-org-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 is still an important part 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 for verification
+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
+
+.. _kernel_org_trust_repository:
+
+Using the kernel.org web of trust repository
+--------------------------------------------
+
+Kernel.org maintains a git repository with developers' public keys as a
+replacement for replicating keyserver networks that have gone mostly
+dark in the past few years. The full documentation for how to set up
+that repository as your source of public keys can be found here:
+
+- `Kernel developer PGP Keyring`_
+
+If you are a kernel developer, please consider submitting your key for
+inclusion into that keyring.
+
+.. _`Kernel developer PGP Keyring`: https://korg.docs.kernel.org/pgpkeys.html