Signed-off-by: Benjamin Peterson <bp@benjamin.pe> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
		
			
				
	
	
		
			388 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			388 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| 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
 |