AEAD ciphers implement a very similar API approach as the symmetric ciphers:
One-shot API: The one-shot API performs an encryption operation with one API call. With that API call, the caller provides the input data and immediately receives the output from the cipher operation.
Stream API: With the stream API, the caller can implement independent calls to send data to the kernel and receive data from the kernel. However, unlike the symmetric cipher API, one AEAD cipher operation must be considered as one unit as the integrity value is calculated for one encryption or decryption operation. The caller can use multiple calls to provide the input data. The last chunk of data must be sent to the kernel with the API call marking the last submission. Then, the cipher operation can be triggered with the recvmsg invocation. It is possible to implement a multi-threaded application as the thread triggering the cipher operation is put to sleep until the last block is received. Once the last block is received, the caller waiting on the cipher operation is woken up to obtain the data.
Similarly to the symmetric cipher API, the AEAD API supports asynchronous operation as well. The same concept regarding the IOVECs applies as discussed for the asynchronous symmetric cipher API above.
When using the stream API for AEAD, the caller must observe a particular order of data components. It is permissible that for each of the following data components multiple send calls are used. But in total, all send calls must send the AEAD data in the requested sequence. That sequence has changed with kernel 4.9. The following sequence is applicable to kernel versions up to and including 4.8:
Associated Authentication Data: The AAD must be provided as a first chunk.
Plaintext / Ciphertext: Following the AAD, the entire plaintext or ciphertext is provided that shall be encrypted and integrity protected or decrypted and whose integrity shall be verified.
Authentication Tag: Regardless of an encryption or decryption, the authentication tag memory must be provided.
The caller must provide memory that is identical in size for the input and output data, even parts of the memory is unused. For example, for encryption, the AEAD cipher operation only needs the AAD and the plaintext. Nonetheless, the interface requires that the memory is big enough to hold the tag as well. This requirement particularly aids the in-place cipher operation.
Starting with kernel 4.9, the interface changed slightly such that the authentication tag memory is only needed in the output buffer for encryption and in the input buffer for decryption.
To allow the calling application to be agnostic about the differences in the kernel interface, the calling application is offered additional API calls which should be used as follows:
Obtain the required input buffer length for the cryptographic operation using the calls kcapi_aead_inbuflen_enc or kcapi_aead_inbuflen_dec.
Obtain the required output buffer length for the cryptographic operation using the APIs of kcapi_aead_outbuflen_enc or kcapi_aead_outbuflen_dec.
For an in-place operation with a linear buffer, do the following (for an example, see test/kcapi-main.c:cavs_aead()):
allocate memory that is max(inbuflen, outbuflen),
call to kcapi_aead_getdata_input and kcapi_aead_getdata_output with the allocated memory pointer to obtain the pointers into that allocated memory where the AAD, plaintext / ciphertext and tag is to be provided,
fill these AAD, plaintext/ciphertext and tag pointers with the respective data if they are non-NULL -- note, a NULL pointer may be returned for the tag pointer,
invoke the crypto operation with the pointer to the allocated buffer and inbuflen is supplied to the.
For for separate, potentially non-contiguous buffers, do the following (for an example, see test/kcapi-main.c:cavs_aead_stream()):
ensure that your total buffer size for input and output complies with the result from the buffer lengths supplied by the aforementioned API calls,
call to kcapi_aead_getdata_input and kcapi_aead_getdata_output with NULL pointers for the memory buffers to obtain the lengths for the AEAD data components,
initialize the IOVECs and/or invoke the stream API with the independent buffers with the AAD, plaintext/ciphertext and tag if the associated length values are non-zero.
If the caller chooses to not implement an in-place operation, the kernel will copy the AAD data into the output buffer, so that the destination buffer will hold the the ciphertext or plaintext, the AAD data and the authentication tag (encryption only). The memory structure of the destination buffer is identical to the source buffer. (This is currently not yet implemented for all ciphers and will be fixed in future kernel versions.)