mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-18 22:59:29 +02:00
Add support for AES-GCM to the crypto library.
This will be used to provide streamlined implementations of the
"gcm(aes)" and "rfc4106(gcm(aes))" crypto_aead algorithms. Most users
of these will also be able to switch to the library, which as usual will
be faster and simpler, e.g.:
- drivers/net/macsec.c
- fs/smb/client/
- fs/smb/server/
- net/ceph/messenger_v2.c
- net/mac80211/ (for both GMAC and GCMP)
- net/tipc/crypto.c
- security/keys/trusted-keys/trusted_dcp.c
(I've already written proof-of-concept patches for all the above, and
they helped inform the API design.)
As usual, the architecture-optimized AES-GCM code will be migrated into
the library as well (using the hooks provided in this commit as well as
the GHASH ones), eliminating lots of repetitive boilerplate code.
Incremental en/decryption is supported. Incremental operation is a bit
controversial in AEAD APIs because users have to be careful not to
consume any decrypted data that hasn't been authenticated yet. But I do
think it's the right choice here. It's not fundamentally different from
the existing incremental MAC APIs, and it's the only approach that's
general enough to work well for all users in the kernel:
- An array of virtually-addressed buffers (like that used by
BoringSSL's EVP_AEAD_CTX_sealv() and EVP_AEAD_CTX_openv()) doesn't
work in the kernel in general, since in some cases the data for a
single AES-GCM message is contained in a large number of highmem
pages that each need to be mapped into memory individually. That
can be done efficiently only by using CPU-local mappings, but there
is a limited number of those.
Ceph messenger v2 is a great example, as it can send or receive up
to 32 MiB in a single AES-GCM message. And it needs the
en/decrypted data to go into a (potentially large) number of bvecs
provided by a custom iterator, as well as into four
virtually-addressed buffers, two of which can be large buffers in
the vmalloc region.
Even just allocating an array big enough to store all the pointers
can be problematic in the kernel. There are cases in which
decryption runs in GFP_NOIO context or even in softirq context,
where memory allocations are not as reliable as they normally are.
- Meanwhile, 'struct scatterlist' (the choice of crypto_aead) has
turned out to be really inconvenient for anyone who *does* just have
virtually-addressed buffers. This is especially true if they can be
in the vmalloc region, including the stack, as in that case the
conversion to a scatterlist has to be done page-by-page.
And even for users who have all of their data in bare 'struct page',
none of them actually use 'struct scatterlist' as their native data
structure anyway. They actually use skbs, bvecs, or other formats.
- iov_iter is attractive, but ultimately not general enough either
(considering the Ceph case for example), but also too general in
some ways (like having support for userspace addresses). Additional
iter types like ITER_SKB would help a bit, but bloating iov_iter
with more types would reduce performance elsewhere in the kernel.
Initial test coverage is provided by the crypto_aead support added in a
later commit. I'm planning a KUnit test suite as well.
Link: https://patch.msgid.link/20260715221153.246410-7-ebiggers@kernel.org
Link: https://patch.msgid.link/20260722021730.16897-1-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
169 lines
7.3 KiB
ReStructuredText
169 lines
7.3 KiB
ReStructuredText
.. SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
==============
|
|
Crypto library
|
|
==============
|
|
|
|
The Linux kernel's crypto library (``lib/crypto/``) provides kernel-internal
|
|
users of cryptographic algorithms with faster and easier access to those
|
|
algorithms than the traditional kernel crypto API.
|
|
|
|
Each cryptographic algorithm is supported via a set of dedicated functions.
|
|
"Crypto agility", where needed, is left to calling code.
|
|
|
|
The crypto library functions are intended to be boring and straightforward, and
|
|
to follow familiar conventions. Their primary documentation is their (fairly
|
|
extensive) kernel-doc. This page just provides some extra high-level context.
|
|
|
|
Note that the crypto library isn't entirely new. ``lib/`` has contained some
|
|
crypto functions since 2005. Rather, it's just an approach that's been expanded
|
|
over time as it's been found to work well. It also largely just matches how the
|
|
kernel already does things elsewhere.
|
|
|
|
Scope and intended audience
|
|
===========================
|
|
|
|
The crypto library documentation is primarily meant for kernel developers who
|
|
need to use a particular cryptographic algorithm(s) in kernel code. For
|
|
example, "I just need to compute a SHA-256 hash." A secondary audience is
|
|
developers working on the crypto algorithm implementations themselves.
|
|
|
|
If you're looking for more general information about cryptography, like the
|
|
differences between the different crypto algorithms or how to select an
|
|
appropriate algorithm, you should refer to external sources which cover that
|
|
type of information much more comprehensively. If you need help selecting
|
|
algorithms for a new kernel feature that doesn't already have its algorithms
|
|
predefined, please reach out to ``linux-crypto@vger.kernel.org`` for advice.
|
|
|
|
Code organization
|
|
=================
|
|
|
|
- ``lib/crypto/*.c``: the crypto algorithm implementations
|
|
|
|
- ``lib/crypto/$(SRCARCH)/``: architecture-specific code for crypto algorithms.
|
|
It is here rather than somewhere in ``arch/`` partly because this allows
|
|
generic and architecture-optimized code to be easily built into a single
|
|
loadable module (when the algorithm is set to 'm' in the kconfig).
|
|
|
|
- ``lib/crypto/tests/``: KUnit tests for the crypto algorithms
|
|
|
|
- ``include/crypto/``: crypto headers, for both the crypto library and the
|
|
traditional crypto API
|
|
|
|
Generally, there is one kernel module per algorithm. Sometimes related
|
|
algorithms are grouped into one module. There is intentionally no common
|
|
framework, though there are some utility functions that multiple algorithms use.
|
|
|
|
Each algorithm module is controlled by a tristate kconfig symbol
|
|
``CRYPTO_LIB_$(ALGORITHM)``. As is the norm for library functions in the
|
|
kernel, these are hidden symbols which don't show up in the kconfig menu.
|
|
Instead, they are just selected by all the kconfig symbols that need them.
|
|
|
|
Many of the algorithms have multiple implementations: a generic implementation
|
|
and architecture-optimized implementation(s). Each module initialization
|
|
function, or initcall in the built-in case, automatically enables the best
|
|
implementation based on the available CPU features.
|
|
|
|
Note that the crypto library doesn't use the ``crypto/``,
|
|
``arch/$(SRCARCH)/crypto/``, or ``drivers/crypto/`` directories. These
|
|
directories are used by the traditional crypto API. When possible, algorithms
|
|
in the traditional crypto API are implemented by calls into the library.
|
|
|
|
Advantages
|
|
==========
|
|
|
|
Some of the advantages of the library over the traditional crypto API are:
|
|
|
|
- The library functions tend to be much easier to use. For example, a hash
|
|
value can be computed using only a single function call. Most of the library
|
|
functions always succeed and return void, eliminating the need to write
|
|
error-handling code. Most also accept standard virtual addresses, rather than
|
|
scatterlists which are difficult and less efficient to work with.
|
|
|
|
- The library functions are usually faster, especially for short inputs. They
|
|
call the crypto algorithms directly without inefficient indirect calls, memory
|
|
allocations, string parsing, lookups in an algorithm registry, and other
|
|
unnecessary API overhead. Architecture-optimized code is enabled by default.
|
|
|
|
- The library functions use standard link-time dependencies instead of
|
|
error-prone dynamic loading by name. There's no need for workarounds such as
|
|
forcing algorithms to be built-in or adding module soft dependencies.
|
|
|
|
- The library focuses on the approach that works the best on the vast majority
|
|
of systems: CPU-based implementations of the crypto algorithms, utilizing
|
|
on-CPU acceleration (such as AES instructions) when available.
|
|
|
|
- The library uses standard KUnit tests, rather than custom ad-hoc tests.
|
|
|
|
- The library tends to have higher assurance implementations of the crypto
|
|
algorithms. This is both due to its simpler design and because more of its
|
|
code is being regularly tested.
|
|
|
|
- The library supports features that don't fit into the rigid framework of the
|
|
traditional crypto API, for example interleaved hashing and XOFs.
|
|
|
|
When to use it
|
|
==============
|
|
|
|
In-kernel users should use the library (rather than the traditional crypto API)
|
|
whenever possible. Many subsystems have already been converted. It usually
|
|
simplifies their code significantly and improves performance.
|
|
|
|
Some kernel features allow userspace to provide an arbitrary string that selects
|
|
an arbitrary algorithm from the traditional crypto API by name. These features
|
|
generally will have to keep using the traditional crypto API for backwards
|
|
compatibility.
|
|
|
|
Note: new kernel features shouldn't support every algorithm, but rather make a
|
|
deliberate choice about what algorithm(s) to support. History has shown that
|
|
making a deliberate, thoughtful choice greatly simplifies code maintenance,
|
|
reduces the chance for mistakes (such as using an obsolete, insecure, or
|
|
inappropriate algorithm), and makes your feature easier to use.
|
|
|
|
Testing
|
|
=======
|
|
|
|
The crypto library uses standard KUnit tests. Like many of the kernel's other
|
|
KUnit tests, they are included in the set of tests that is run by
|
|
``tools/testing/kunit/kunit.py run --alltests``.
|
|
|
|
A ``.kunitconfig`` file is also provided to run just the crypto library tests.
|
|
For example, here's how to run them in user-mode Linux:
|
|
|
|
.. code-block:: sh
|
|
|
|
tools/testing/kunit/kunit.py run --kunitconfig=lib/crypto/
|
|
|
|
Many of the crypto algorithms have architecture-optimized implementations.
|
|
Testing those requires building an appropriate kernel and running the tests
|
|
either in QEMU or on appropriate hardware. Here's one example with QEMU:
|
|
|
|
.. code-block:: sh
|
|
|
|
tools/testing/kunit/kunit.py run --kunitconfig=lib/crypto/ --arch=arm64 --make_options LLVM=1
|
|
|
|
Depending on the code being tested, flags may need to be passed to QEMU to
|
|
emulate the correct type of hardware for the code to be reached.
|
|
|
|
Since correctness is essential in cryptographic code, new architecture-optimized
|
|
code is accepted only if it can be tested in QEMU.
|
|
|
|
Note: the crypto library also includes FIPS 140 self-tests. These are
|
|
lightweight, are designed specifically to meet FIPS 140 requirements, and exist
|
|
*only* to meet those requirements. Normal testing done by kernel developers and
|
|
integrators should use the much more comprehensive KUnit tests instead.
|
|
|
|
API documentation
|
|
=================
|
|
|
|
.. toctree::
|
|
:maxdepth: 2
|
|
|
|
libcrypto-auth-encryption
|
|
libcrypto-blockcipher
|
|
libcrypto-hash
|
|
libcrypto-signature
|
|
libcrypto-unauth-encryption
|
|
libcrypto-utils
|
|
sha3
|