User Space Interface

Introduction

The concepts of the kernel crypto API visible to kernel space is fullyapplicable to the user space interface as well. Therefore, the kernelcrypto API high level discussion for the in-kernel use cases applieshere as well.

The major difference, however, is that user space can only act as aconsumer and never as a provider of a transformation or cipheralgorithm.

The following covers the user space interface exported by the kernelcrypto API. A working example of this description is libkcapi that canbe obtained from [1]. That library can be used by user spaceapplications that require cryptographic services from the kernel.

Some details of the in-kernel kernel crypto API aspects do not apply touser space, however. This includes the difference between synchronousand asynchronous invocations. The user space API call is fullysynchronous.

[1]https://www.chronox.de/libkcapi.html

User Space API General Remarks

The kernel crypto API is accessible from user space. Currently, thefollowing 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. Inaddition, the setsockopt option type is SOL_ALG. In case the user spaceheader 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 APIcalls. This includes the generic vs. unique naming schema for ciphers aswell as the enforcement of priorities for generic names.

To interact with the kernel crypto API, a socket must be created by theuser space application. User space invokes the cipher operation with thesend()/write() system call family. The result of the cipher operation isobtained with the read()/recv() system call family.

The following API calls assume that the socket descriptor is alreadyopened by the user space application and discusses only the kernelcrypto API specific invocations.

To initialize the socket interface, the following sequence has to beperformed by the consumer:

  1. Create a socket of type AF_ALG with thestructsockaddr_algparameter specified below for the different cipher types.

  2. Invoke bind with the socket descriptor

  3. Invoke accept with the socket descriptor. The accept system callreturns a new file descriptor that is to be used to interact with theparticular cipher instance. When invoking send/write or recv/readsystem calls to send data to the kernel or obtain data from thekernel, 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 userspace interface allows the cipher operation in-place. That means thatthe input buffer used for the send/write system call and the outputbuffer used by the read/recv system call may be one and the same. Thisis of particular interest for symmetric cipher operations where acopying of the output data to its final destination can be avoided.

If a consumer on the other hand wants to maintain the plaintext and theciphertext in different memory locations, all a consumer needs to do isto provide different memory pointers for the encryption and decryptionoperation.

Message Digest API

The message digest type to be used for the cipher operation is selectedwhen invoking the bind syscall. bind requires the caller to provide afilledstructsockaddr data structure. This data structure must befilled 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 messagedigests. Though, a keyed message digest is referenced by the appropriatesalg_name. Please see below for the setsockopt interface that explainshow the key can be set for a keyed message digest.

Using thesend() system call, the application provides the data thatshould be processed with the message digest. The send system call allowsthe following flags to be specified:

  • MSG_MORE: If this flag is set, the send system call acts like amessage digest update function where the final hash is not yetcalculated. If the flag is not set, the send system call calculatesthe final message digest immediately.

With therecv() system call, the application can read the message digestfrom the kernel crypto API. If the buffer is too small for the messagedigest, the flag MSG_TRUNC is set by the kernel.

In order to set a message digest key, the calling application must usethesetsockopt() option of ALG_SET_KEY or ALG_SET_KEY_BY_KEY_SERIAL. If thekey is not set the HMAC operation is performed without the initial HMAC statechange caused by the key.

Symmetric Cipher API

The operation is very similar to the message digest discussion. Duringinitialization, thestructsockaddr data structure must be filled asfollows:

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 callfamily, the consumer must set the key. The key setting is described withthe setsockopt invocation below.

Using thesendmsg() system call, the application provides the data thatshould be processed for encryption or decryption. In addition, the IV isspecified with the data structure provided by thesendmsg() system call.

The sendmsg system call parameter ofstructmsghdr is embedded into thestructcmsghdr data structure. See recv(2) and cmsg(3) for moreinformation on how the cmsghdr data structure is used together with thesend/recv system call family. That cmsghdr data structure holds thefollowing 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 acipher update function where more input data is expected with asubsequent invocation of the send system call.

Note: The kernel reports -EINVAL for any unexpected data. The callermust make sure that all data matches the constraints given in/proc/crypto for the selected cipher.

With therecv() system call, the application can read the result of thecipher operation from the kernel crypto API. The output buffer must beat least as large as to hold all blocks of the encrypted or decrypteddata. If the output data size is smaller, only as many blocks arereturned that fit into that output buffer size.

AEAD Cipher API

The operation is very similar to the symmetric cipher discussion. Duringinitialization, thestructsockaddr data structure must be filled asfollows:

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 callfamily, the consumer must set the key. The key setting is described withthe setsockopt invocation below.

In addition, before data can be sent to the kernel using the write/sendsystem call family, the consumer must set the authentication tag size.To set the authentication tag size, the caller must use the setsockoptinvocation described below.

Using thesendmsg() system call, the application provides the data thatshould be processed for encryption or decryption. In addition, the IV isspecified with the data structure provided by thesendmsg() system call.

The sendmsg system call parameter ofstructmsghdr is embedded into thestructcmsghdr data structure. See recv(2) and cmsg(3) for moreinformation on how the cmsghdr data structure is used together with thesend/recv system call family. That cmsghdr data structure holds thefollowing 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 theflag ALG_SET_AEAD_ASSOCLEN. The AAD is sent to the kernel togetherwith 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 acipher update function where more input data is expected with asubsequent invocation of the send system call.

Note: The kernel reports -EINVAL for any unexpected data. The callermust make sure that all data matches the constraints given in/proc/crypto for the selected cipher.

With therecv() system call, the application can read the result of thecipher operation from the kernel crypto API. The output buffer must beat least as large as defined with the memory structure below. If theoutput 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 iscommunicated 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 thesendmsg and setsockopt calls (see there). As the kernel knows the sizeof the entire data stream, the kernel is now able to calculate the rightoffsets of the data components in the data stream.

The user space caller must arrange the aforementioned information in thefollowing 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 aslarge 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. Duringinitialization, thestructsockaddr data structure must be filled asfollows:

struct sockaddr_alg sa = {    .salg_family = AF_ALG,    .salg_type = "rng", /* this selects the random number generator */    .salg_name = "drbg_nopr_sha256" /* this is the RNG name */};

Depending on the RNG type, the RNG must be seeded. The seed is providedusing the setsockopt interface to set the key. For example, theansi_cprng requires a seed. The DRBGs do not require a seed, but may beseeded. The seed is also known as aPersonalization String in NIST SP 800-90Astandard.

Using the read()/recvmsg() system calls, random numbers can be obtained.The kernel generates at most 128 bytes in one call. If user spacerequires more data, multiple calls to read()/recvmsg() must be made.

WARNING: The user space caller may invoke the initially mentioned acceptsystem call multiple times. In this case, the returned file descriptorshave the same state.

Following CAVP testing interfaces are enabled when kernel is built withCRYPTO_USER_API_RNG_CAVP option:

  • the concatenation ofEntropy andNonce can be provided to the RNG viaALG_SET_DRBG_ENTROPY setsockopt interface. Setting the entropy requiresCAP_SYS_ADMIN permission.

  • Additional Data can be provided using thesend()/sendmsg() system calls,but only after the entropy has been set.

Zero-Copy Interface

In addition to the send/write/read/recv system call family, the AF_ALGinterface can be accessed with the zero-copy interface ofsplice/vmsplice. As the name indicates, the kernel tries to avoid a copyoperation into kernel space.

The zero-copy operation requires data to be aligned at the pageboundary. Non-aligned data can be used as well, but may require moreoperations of the kernel which would defeat the speed gains obtainedfrom the zero-copy interface.

The system-inherent limit for the size of one zero-copy operation is 16pages. If more data is to be sent to AF_ALG, user space must slice theinput into segments with a maximum size of 16 pages.

Zero-copy can be used with the following code example (a completeworking 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 sendand retrieve data subject to the cipher operation, a consumer also needsto set the additional information for the cipher operation. Thisadditional information is set using the setsockopt system call that mustbe invoked with the file descriptor of the open cipher (i.e. the filedescriptor returned by the accept system call).

Each setsockopt invocation must use the level SOL_ALG.

The setsockopt interface allows setting the following data using thementioned 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 decrypteddata is copied from a keyring key, and uses that data as thekey for symmetric encryption.

    The passed in key_serial_t must have the KEY_(POS|USR|GRP|OTH)_SEARCHpermission set, otherwise -EPERM is returned. Supports key types: user,logon, encrypted, and trusted.

  • ALG_SET_AEAD_AUTHSIZE -- Setting the authentication tag size forAEAD ciphers. For a encryption operation, the authentication tag ofthe given size will be generated. For a decryption operation, theprovided ciphertext is assumed to contain an authentication tag ofthe 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 aroundthe aforementioned Netlink kernel interface. [1] also contains a testapplication that invokes all libkcapi API calls.

[1]https://www.chronox.de/libkcapi.html