mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-08-09 06:14:34 +02:00
Without support for zero-copy or off-CPU offloads, AF_ALG is always slower than software cryptography. Its only advantage is that it might save code size. However, this is largely mitigated by lightweight userspace cryptographic libraries. Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
449 lines
17 KiB
ReStructuredText
449 lines
17 KiB
ReStructuredText
User Space Interface
|
|
====================
|
|
|
|
Introduction
|
|
------------
|
|
|
|
AF_ALG provides unprivileged userspace programs access to arbitrary hash,
|
|
symmetric cipher, AEAD, and RNG algorithms that are implemented in kernel-mode
|
|
code.
|
|
|
|
AF_ALG is insecure and is deprecated. Originally added to the kernel in 2010,
|
|
most kernel developers now consider it to be a mistake. Support for hardware
|
|
accelerators, which was the original purpose of AF_ALG, has been removed.
|
|
|
|
AF_ALG continues to be supported only for backwards compatibility. On systems
|
|
where no programs using AF_ALG remain, the support for it should be disabled by
|
|
disabling ``CONFIG_CRYPTO_USER_API_*``.
|
|
|
|
Deprecation
|
|
-----------
|
|
|
|
AF_ALG was originally intended to provide userspace programs access to crypto
|
|
accelerators that they wouldn't otherwise have access to.
|
|
|
|
However, that capability turned out to not be useful on very many systems. More
|
|
significantly, the actual implementation exposes a vastly greater amount of
|
|
functionality than that. It actually provides access to all software algorithms.
|
|
|
|
This includes arbitrary compositions of different algorithms created via a
|
|
complex template system, as well as algorithms that only make sense as internal
|
|
implementation details of other algorithms. In the past, it also included full
|
|
zero-copy support, which was difficult for the kernel to implement securely.
|
|
|
|
Ultimately, these algorithms are just math computations. They use the same
|
|
instructions that userspace programs already have access to, just accessed in a
|
|
much more convoluted and less efficient way.
|
|
|
|
Indeed, userspace code is nearly always what is being used anyway. These same
|
|
algorithms are widely implemented in userspace crypto libraries.
|
|
|
|
Even when zero-copy and off-CPU accelerators were supported, AF_ALG was usually
|
|
much slower than optimized software cryptography in userspace. This was
|
|
especially true for the small message sizes usually seen in performance-critical
|
|
workloads. While it was possible to demonstrate performance wins for hashing
|
|
large files on embedded devices, it is hard to imagine a situation where this
|
|
would be performance-critical.
|
|
|
|
Nowadays, AF_ALG no longer supports zero-copy or off-CPU accelerators.
|
|
Therefore, it is *always* slower than an optimized userspace implementation,
|
|
even for large messages. The only possible advantage left is that it avoids
|
|
duplicating code between kernel and userspace. However, userspace
|
|
implementations, especially hardware-accelerated ones, do not need to be large.
|
|
Just because OpenSSL is huge does not mean that all userspace cryptography
|
|
libraries are.
|
|
|
|
Meanwhile, AF_ALG hasn't been withstanding modern vulnerability discovery tools
|
|
such as syzbot and large language models. It receives a steady stream of CVEs.
|
|
Some of the examples include:
|
|
|
|
- CVE-2026-31677
|
|
- CVE-2026-31431 (https://copy.fail)
|
|
- CVE-2025-38079
|
|
- CVE-2025-37808
|
|
- CVE-2024-26824
|
|
- CVE-2022-48781
|
|
- CVE-2019-8912
|
|
- CVE-2018-14619
|
|
- CVE-2017-18075
|
|
- CVE-2017-17806
|
|
- CVE-2017-17805
|
|
- CVE-2016-10147
|
|
- CVE-2015-8970
|
|
- CVE-2015-3331
|
|
- CVE-2014-9644
|
|
- CVE-2013-7421
|
|
- CVE-2011-4081
|
|
|
|
Hardware accelerator drivers are frequently buggy. To reduce attack surface,
|
|
AF_ALG now only provides access to algorithms implemented in software. This
|
|
means that AF_ALG no longer fulfills its original purpose.
|
|
|
|
It is recommended that, whenever possible, userspace programs be migrated to
|
|
userspace crypto code (which again, is what is normally used anyway) and
|
|
``CONFIG_CRYPTO_USER_API_*`` be disabled. On systems that use SELinux, SELinux
|
|
can also be used to restrict the use of AF_ALG to trusted programs.
|
|
|
|
The remainder of this documentation provides the historical documentation for
|
|
the deprecated AF_ALG interface.
|
|
|
|
User Space API General Remarks
|
|
------------------------------
|
|
|
|
The kernel crypto API is accessible from user space. Currently, the
|
|
following ciphers are accessible:
|
|
|
|
- Message digest including keyed message digest (HMAC, CMAC)
|
|
|
|
- Symmetric ciphers
|
|
|
|
- AEAD ciphers
|
|
|
|
- Random Number Generators
|
|
|
|
The interface is provided via socket type using the type AF_ALG. In
|
|
addition, the setsockopt option type is SOL_ALG. In case the user space
|
|
header files do not export these flags yet, use the following macros:
|
|
|
|
::
|
|
|
|
#ifndef AF_ALG
|
|
#define AF_ALG 38
|
|
#endif
|
|
#ifndef SOL_ALG
|
|
#define SOL_ALG 279
|
|
#endif
|
|
|
|
|
|
A cipher is accessed with the same name as done for the in-kernel API
|
|
calls. This includes the generic vs. unique naming schema for ciphers as
|
|
well as the enforcement of priorities for generic names.
|
|
|
|
To interact with the kernel crypto API, a socket must be created by the
|
|
user space application. User space invokes the cipher operation with the
|
|
send()/write() system call family. The result of the cipher operation is
|
|
obtained with the read()/recv() system call family.
|
|
|
|
The following API calls assume that the socket descriptor is already
|
|
opened by the user space application and discusses only the kernel
|
|
crypto API specific invocations.
|
|
|
|
To initialize the socket interface, the following sequence has to be
|
|
performed by the consumer:
|
|
|
|
1. Create a socket of type AF_ALG with the struct sockaddr_alg
|
|
parameter specified below for the different cipher types.
|
|
|
|
2. Invoke bind with the socket descriptor
|
|
|
|
3. Invoke accept with the socket descriptor. The accept system call
|
|
returns a new file descriptor that is to be used to interact with the
|
|
particular cipher instance. When invoking send/write or recv/read
|
|
system calls to send data to the kernel or obtain data from the
|
|
kernel, the file descriptor returned by accept must be used.
|
|
|
|
In-place Cipher operation
|
|
-------------------------
|
|
|
|
Just like the in-kernel operation of the kernel crypto API, the user
|
|
space interface allows the cipher operation in-place. That means that
|
|
the input buffer used for the send/write system call and the output
|
|
buffer used by the read/recv system call may be one and the same. This
|
|
is of particular interest for symmetric cipher operations where a
|
|
copying of the output data to its final destination can be avoided.
|
|
|
|
If a consumer on the other hand wants to maintain the plaintext and the
|
|
ciphertext in different memory locations, all a consumer needs to do is
|
|
to provide different memory pointers for the encryption and decryption
|
|
operation.
|
|
|
|
Message Digest API
|
|
------------------
|
|
|
|
The message digest type to be used for the cipher operation is selected
|
|
when invoking the bind syscall. bind requires the caller to provide a
|
|
filled struct sockaddr data structure. This data structure must be
|
|
filled as follows:
|
|
|
|
::
|
|
|
|
struct sockaddr_alg sa = {
|
|
.salg_family = AF_ALG,
|
|
.salg_type = "hash", /* this selects the hash logic in the kernel */
|
|
.salg_name = "sha1" /* this is the cipher name */
|
|
};
|
|
|
|
|
|
The salg_type value "hash" applies to message digests and keyed message
|
|
digests. Though, a keyed message digest is referenced by the appropriate
|
|
salg_name. Please see below for the setsockopt interface that explains
|
|
how the key can be set for a keyed message digest.
|
|
|
|
Using the send() system call, the application provides the data that
|
|
should be processed with the message digest. The send system call allows
|
|
the following flags to be specified:
|
|
|
|
- MSG_MORE: If this flag is set, the send system call acts like a
|
|
message digest update function where the final hash is not yet
|
|
calculated. If the flag is not set, the send system call calculates
|
|
the final message digest immediately.
|
|
|
|
With the recv() system call, the application can read the message digest
|
|
from the kernel crypto API. If the buffer is too small for the message
|
|
digest, the flag MSG_TRUNC is set by the kernel.
|
|
|
|
In order to set a message digest key, the calling application must use
|
|
the setsockopt() option of ALG_SET_KEY or ALG_SET_KEY_BY_KEY_SERIAL. If the
|
|
key is not set the HMAC operation is performed without the initial HMAC state
|
|
change caused by the key.
|
|
|
|
Symmetric Cipher API
|
|
--------------------
|
|
|
|
The operation is very similar to the message digest discussion. During
|
|
initialization, the struct sockaddr data structure must be filled as
|
|
follows:
|
|
|
|
::
|
|
|
|
struct sockaddr_alg sa = {
|
|
.salg_family = AF_ALG,
|
|
.salg_type = "skcipher", /* this selects the symmetric cipher */
|
|
.salg_name = "cbc(aes)" /* this is the cipher name */
|
|
};
|
|
|
|
|
|
Before data can be sent to the kernel using the write/send system call
|
|
family, the consumer must set the key. The key setting is described with
|
|
the setsockopt invocation below.
|
|
|
|
Using the sendmsg() system call, the application provides the data that
|
|
should be processed for encryption or decryption. In addition, the IV is
|
|
specified with the data structure provided by the sendmsg() system call.
|
|
|
|
The sendmsg system call parameter of struct msghdr is embedded into the
|
|
struct cmsghdr data structure. See recv(2) and cmsg(3) for more
|
|
information on how the cmsghdr data structure is used together with the
|
|
send/recv system call family. That cmsghdr data structure holds the
|
|
following information specified with a separate header instances:
|
|
|
|
- specification of the cipher operation type with one of these flags:
|
|
|
|
- ALG_OP_ENCRYPT - encryption of data
|
|
|
|
- ALG_OP_DECRYPT - decryption of data
|
|
|
|
- specification of the IV information marked with the flag ALG_SET_IV
|
|
|
|
The send system call family allows the following flag to be specified:
|
|
|
|
- MSG_MORE: If this flag is set, the send system call acts like a
|
|
cipher update function where more input data is expected with a
|
|
subsequent invocation of the send system call.
|
|
|
|
Note: The kernel reports -EINVAL for any unexpected data. The caller
|
|
must make sure that all data matches the constraints given in
|
|
/proc/crypto for the selected cipher.
|
|
|
|
With the recv() system call, the application can read the result of the
|
|
cipher operation from the kernel crypto API. The output buffer must be
|
|
at least as large as to hold all blocks of the encrypted or decrypted
|
|
data. If the output data size is smaller, only as many blocks are
|
|
returned that fit into that output buffer size.
|
|
|
|
AEAD Cipher API
|
|
---------------
|
|
|
|
The operation is very similar to the symmetric cipher discussion. During
|
|
initialization, the struct sockaddr data structure must be filled as
|
|
follows:
|
|
|
|
::
|
|
|
|
struct sockaddr_alg sa = {
|
|
.salg_family = AF_ALG,
|
|
.salg_type = "aead", /* this selects the symmetric cipher */
|
|
.salg_name = "gcm(aes)" /* this is the cipher name */
|
|
};
|
|
|
|
|
|
Before data can be sent to the kernel using the write/send system call
|
|
family, the consumer must set the key. The key setting is described with
|
|
the setsockopt invocation below.
|
|
|
|
In addition, before data can be sent to the kernel using the write/send
|
|
system call family, the consumer must set the authentication tag size.
|
|
To set the authentication tag size, the caller must use the setsockopt
|
|
invocation described below.
|
|
|
|
Using the sendmsg() system call, the application provides the data that
|
|
should be processed for encryption or decryption. In addition, the IV is
|
|
specified with the data structure provided by the sendmsg() system call.
|
|
|
|
The sendmsg system call parameter of struct msghdr is embedded into the
|
|
struct cmsghdr data structure. See recv(2) and cmsg(3) for more
|
|
information on how the cmsghdr data structure is used together with the
|
|
send/recv system call family. That cmsghdr data structure holds the
|
|
following information specified with a separate header instances:
|
|
|
|
- specification of the cipher operation type with one of these flags:
|
|
|
|
- ALG_OP_ENCRYPT - encryption of data
|
|
|
|
- ALG_OP_DECRYPT - decryption of data
|
|
|
|
- specification of the IV information marked with the flag ALG_SET_IV
|
|
|
|
- specification of the associated authentication data (AAD) with the
|
|
flag ALG_SET_AEAD_ASSOCLEN. The AAD is sent to the kernel together
|
|
with the plaintext / ciphertext. See below for the memory structure.
|
|
|
|
The send system call family allows the following flag to be specified:
|
|
|
|
- MSG_MORE: If this flag is set, the send system call acts like a
|
|
cipher update function where more input data is expected with a
|
|
subsequent invocation of the send system call.
|
|
|
|
Note: The kernel reports -EINVAL for any unexpected data. The caller
|
|
must make sure that all data matches the constraints given in
|
|
/proc/crypto for the selected cipher.
|
|
|
|
With the recv() system call, the application can read the result of the
|
|
cipher operation from the kernel crypto API. The output buffer must be
|
|
at least as large as defined with the memory structure below. If the
|
|
output data size is smaller, the cipher operation is not performed.
|
|
|
|
The authenticated decryption operation may indicate an integrity error.
|
|
Such breach in integrity is marked with the -EBADMSG error code.
|
|
|
|
AEAD Memory Structure
|
|
~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The AEAD cipher operates with the following information that is
|
|
communicated between user and kernel space as one data stream:
|
|
|
|
- plaintext or ciphertext
|
|
|
|
- associated authentication data (AAD)
|
|
|
|
- authentication tag
|
|
|
|
The sizes of the AAD and the authentication tag are provided with the
|
|
sendmsg and setsockopt calls (see there). As the kernel knows the size
|
|
of the entire data stream, the kernel is now able to calculate the right
|
|
offsets of the data components in the data stream.
|
|
|
|
The user space caller must arrange the aforementioned information in the
|
|
following order:
|
|
|
|
- AEAD encryption input: AAD \|\| plaintext
|
|
|
|
- AEAD decryption input: AAD \|\| ciphertext \|\| authentication tag
|
|
|
|
The output buffer the user space caller provides must be at least as
|
|
large to hold the following data:
|
|
|
|
- AEAD encryption output: ciphertext \|\| authentication tag
|
|
|
|
- AEAD decryption output: plaintext
|
|
|
|
Random Number Generator API
|
|
---------------------------
|
|
|
|
Again, the operation is very similar to the other APIs. During
|
|
initialization, the struct sockaddr data structure must be filled as
|
|
follows:
|
|
|
|
::
|
|
|
|
struct sockaddr_alg sa = {
|
|
.salg_family = AF_ALG,
|
|
.salg_type = "rng", /* this selects the random number generator */
|
|
.salg_name = "stdrng" /* this is the RNG name */
|
|
};
|
|
|
|
|
|
Depending on the RNG type, the RNG must be seeded. The seed is provided
|
|
using the setsockopt interface to set the key. The SP800-90A DRBGs do
|
|
not require a seed, but may be seeded. The seed is also known as a
|
|
*Personalization String* in NIST SP 800-90A standard.
|
|
|
|
Using the read()/recvmsg() system calls, random numbers can be obtained.
|
|
The kernel generates at most 128 bytes in one call. If user space
|
|
requires more data, multiple calls to read()/recvmsg() must be made.
|
|
|
|
WARNING: The user space caller may invoke the initially mentioned accept
|
|
system call multiple times. In this case, the returned file descriptors
|
|
have the same state.
|
|
|
|
Following CAVP testing interfaces are enabled when kernel is built with
|
|
CRYPTO_USER_API_RNG_CAVP option:
|
|
|
|
- the concatenation of *Entropy* and *Nonce* can be provided to the RNG via
|
|
ALG_SET_DRBG_ENTROPY setsockopt interface. Setting the entropy requires
|
|
CAP_SYS_ADMIN permission.
|
|
|
|
- *Additional Data* can be provided using the send()/sendmsg() system calls,
|
|
but only after the entropy has been set.
|
|
|
|
Zero-Copy Interface
|
|
-------------------
|
|
|
|
AF_ALG used to have zero-copy support, but it was removed due to it being a
|
|
frequent source of vulnerabilities. For backwards compatibility the splice()
|
|
and sendfile() system calls are still supported, but the kernel will make an
|
|
internal copy of the data before passing it to the crypto code.
|
|
|
|
|
|
Setsockopt Interface
|
|
--------------------
|
|
|
|
In addition to the read/recv and send/write system call handling to send
|
|
and retrieve data subject to the cipher operation, a consumer also needs
|
|
to set the additional information for the cipher operation. This
|
|
additional information is set using the setsockopt system call that must
|
|
be invoked with the file descriptor of the open cipher (i.e. the file
|
|
descriptor returned by the accept system call).
|
|
|
|
Each setsockopt invocation must use the level SOL_ALG.
|
|
|
|
The setsockopt interface allows setting the following data using the
|
|
mentioned optname:
|
|
|
|
- ALG_SET_KEY -- Setting the key. Key setting is applicable to:
|
|
|
|
- the skcipher cipher type (symmetric ciphers)
|
|
|
|
- the hash cipher type (keyed message digests)
|
|
|
|
- the AEAD cipher type
|
|
|
|
- the RNG cipher type to provide the seed
|
|
|
|
- ALG_SET_KEY_BY_KEY_SERIAL -- Setting the key via keyring key_serial_t.
|
|
This operation behaves the same as ALG_SET_KEY. The decrypted
|
|
data is copied from a keyring key, and uses that data as the
|
|
key for symmetric encryption.
|
|
|
|
The passed in key_serial_t must have the KEY_(POS|USR|GRP|OTH)_SEARCH
|
|
permission set, otherwise -EPERM is returned. Supports key types: user,
|
|
logon, encrypted, and trusted.
|
|
|
|
- ALG_SET_AEAD_AUTHSIZE -- Setting the authentication tag size for
|
|
AEAD ciphers. For a encryption operation, the authentication tag of
|
|
the given size will be generated. For a decryption operation, the
|
|
provided ciphertext is assumed to contain an authentication tag of
|
|
the given size (see section about AEAD memory layout below).
|
|
|
|
- ALG_SET_DRBG_ENTROPY -- Setting the entropy of the random number generator.
|
|
This option is applicable to RNG cipher type only.
|
|
|
|
User space API example
|
|
----------------------
|
|
|
|
Please see [1] for libkcapi which provides an easy-to-use wrapper around
|
|
the aforementioned Netlink kernel interface. [1] also contains a test
|
|
application that invokes all libkcapi API calls.
|
|
|
|
[1] https://www.chronox.de/libkcapi/index.html
|