123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387 |
- User Space Interface
- ====================
- Introduction
- ------------
- The concepts of the kernel crypto API visible to kernel space is fully
- applicable to the user space interface as well. Therefore, the kernel
- crypto API high level discussion for the in-kernel use cases applies
- here as well.
- The major difference, however, is that user space can only act as a
- consumer and never as a provider of a transformation or cipher
- algorithm.
- The following covers the user space interface exported by the kernel
- crypto API. A working example of this description is libkcapi that can
- be obtained from [1]. That library can be used by user space
- applications that require cryptographic services from the kernel.
- Some details of the in-kernel kernel crypto API aspects do not apply to
- user space, however. This includes the difference between synchronous
- and asynchronous invocations. The user space API call is fully
- synchronous.
- [1] http://www.chronox.de/libkcapi.html
- 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. 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 symmetric cipher */
- .salg_name = "drbg_nopr_sha256" /* this is the cipher name */
- };
- Depending on the RNG type, the RNG must be seeded. The seed is provided
- using the setsockopt interface to set the key. For example, the
- ansi_cprng requires a seed. The DRBGs do not require a seed, but may be
- seeded.
- 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.
- Zero-Copy Interface
- -------------------
- In addition to the send/write/read/recv system call family, the AF_ALG
- interface can be accessed with the zero-copy interface of
- splice/vmsplice. As the name indicates, the kernel tries to avoid a copy
- operation into kernel space.
- The zero-copy operation requires data to be aligned at the page
- boundary. Non-aligned data can be used as well, but may require more
- operations of the kernel which would defeat the speed gains obtained
- from the zero-copy interface.
- The system-inherent limit for the size of one zero-copy operation is 16
- pages. If more data is to be sent to AF_ALG, user space must slice the
- input into segments with a maximum size of 16 pages.
- Zero-copy can be used with the following code example (a complete
- working example is provided with libkcapi):
- ::
- int pipes[2];
- pipe(pipes);
- /* input data in iov */
- vmsplice(pipes[1], iov, iovlen, SPLICE_F_GIFT);
- /* opfd is the file descriptor returned from accept() system call */
- splice(pipes[0], NULL, opfd, NULL, ret, 0);
- read(opfd, out, outlen);
- 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_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).
- 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] http://www.chronox.de/libkcapi.html
|