mirror of https://gitee.com/openkylin/linux.git
206 lines
8.1 KiB
Plaintext
206 lines
8.1 KiB
Plaintext
|
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.
|
||
|
In addition, only a subset of all cipher types are available as documented
|
||
|
below.
|
||
|
|
||
|
|
||
|
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
|
||
|
|
||
|
Note, AEAD ciphers are currently not supported via the symmetric cipher
|
||
|
interface.
|
||
|
|
||
|
The interface is provided via Netlink 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 Netlink 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 Netlink socket descriptor is already
|
||
|
opened by the user space application and discusses only the kernel crypto API
|
||
|
specific invocations.
|
||
|
|
||
|
To initialize a Netlink 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.
|
||
|
|
||
|
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)
|
||
|
|
||
|
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
|
||
|
|
||
|
Author
|
||
|
======
|
||
|
|
||
|
Stephan Mueller <smueller@chronox.de>
|