diff options
Diffstat (limited to 'Documentation/crypto/userspace-if.rst')
| -rw-r--r-- | Documentation/crypto/userspace-if.rst | 455 |
1 files changed, 455 insertions, 0 deletions
diff --git a/Documentation/crypto/userspace-if.rst b/Documentation/crypto/userspace-if.rst new file mode 100644 index 000000000..d6194346e --- /dev/null +++ b/Documentation/crypto/userspace-if.rst @@ -0,0 +1,455 @@ +.. _crypto_userspace_interface: + +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. + +Starting in Linux v7.3, the set of algorithms supported by AF_ALG is limited by +default. See :ref:`/proc/sys/crypto/af_alg_restrict <af_alg_restrict>`. + +On systems where no programs using AF_ALG remain, the support for it should be +disabled entirely by setting ``/proc/sys/crypto/af_alg_restrict`` to 2 or by +disabling ``CONFIG_CRYPTO_USER_API_*`` in the kernel configuration. + +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 |
