linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] kernel crypto API interface specification
@ 2014-10-14 19:46 Stephan Mueller
  2014-10-14 20:00 ` Stephan Mueller
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Stephan Mueller @ 2014-10-14 19:46 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller; +Cc: linux-crypto, linux-kernel

The update adds a complete interface documentation of the kernel crypto
API. All cipher types supported by the kernel crypto API are documented.

In addition, kernel and user space example code is provided. The sample
code covers synchronous and asynchronous cipher operation, random
number generation and performing hashing as well as encryption and
decryption in user space.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 Documentation/crypto/crypto-API-spec.txt | 2110 ++++++++++++++++++++++++++++++
 1 file changed, 2110 insertions(+)
 create mode 100644 Documentation/crypto/crypto-API-spec.txt

diff --git a/Documentation/crypto/crypto-API-spec.txt b/Documentation/crypto/crypto-API-spec.txt
new file mode 100644
index 0000000..027fd4f
--- /dev/null
+++ b/Documentation/crypto/crypto-API-spec.txt
@@ -0,0 +1,2110 @@
+Kernel Crypto API Interface Specification
+=========================================
+
+The kernel crypto API offers a rich set of ciphers and methods to invoke these
+ciphers. This document contains a description of the API and provides example
+code.
+
+To understand and properly use the kernel crypto API a brief explanation of the
+structure is given. Based on the architecture, the API can be separated into
+different components. Following the architecture specification the various
+components forming the kernel crypto API are described.
+
+The kernel crypto API refers to all algorithms as "transforms". Therefore, a
+cipher handle variable usually has the name "tfm". Besides cryptographic
+operations, the kernel crypto API also knows compression transforms and handles
+them the same way as ciphers.
+
+The kernel crypto API serves the following entity types:
+
+	* users requesting cryptographic services
+
+	* data transformation implementations (typically ciphers) that
+	  can be called by users
+
+This specification is mainly intended for normal users that need cryptographic
+support. It lists all API calls relevant for these users. This API
+specification, however, does not list all API calls available to data
+transformation implementations ((i.e. implementations of ciphers and other
+transformations (such as CRC or even compression algorithms) that can register
+with the kernel crypto API).
+
+Kernel Crypto API Architecture
+==============================
+
+Cipher types
+------------
+
+The kernel crypto API provides different API calls for the following cipher
+types:
+
+	* Symmetric ciphers
+
+	* AEAD ciphers
+
+	* Message digest, including keyed message digest
+
+	* Random number generation
+
+	* User space interface
+
+Ciphers and Templates
+---------------------
+
+The kernel crypto API provides implementations of raw ciphers. In addition, the
+kernel crypto API provides numerous "templates" that can be used in conjunction
+with the raw ciphers. Templates include all types of block chaining mode, the
+HMAC mechanism, etc.
+
+Raw ciphers can either be directly used by a caller or invoked together with a
+template. A raw cipher may even be called with multiple templates. However,
+templates cannot be used without a raw cipher.
+
+Synchronous and asynchronous operation
+--------------------------------------
+
+The kernel crypto API provides synchronous and asynchronous API calls.
+
+When using a synchronous API call, the caller invokes a cipher operation which
+is performed synchronously by the kernel crypto API. That means, the caller
+waits until the cipher operation completes. Therefore, the kernel crypto
+API calls work like regular function calls. For synchronous operations, the set
+of API calls is small and similar to any other crypto library.
+
+Asynchronous operation is provided by the kernel crypto API which implies that
+the invocation of a cipher operation will complete almost instantly. That
+invocation triggers the cipher operation but it does not signal its completion.
+Before invoking a cipher operation, the caller must provide a callback function
+the kernel crypto API can invoke to signal the completion of the cipher
+operation. Furthermore, the caller must ensure it can handle such asynchronous
+events by applying appropriate locking around its data. The kernel crypto API
+does not perform any special serialization operation to protect the caller's
+data integrity.
+
+Kernel crypto API cipher references and priority
+------------------------------------------------
+
+A cipher is referenced by the caller with a string. That string has the
+following semantics:
+
+	template(raw cipher)
+
+where "template" and "raw cipher" is the aforementioned template and raw cipher,
+respectively. If applicable, additional templates may enclose other templates,
+such as
+
+	template1(template2(raw cipher)))
+
+The kernel crypto API may provide multiple implementations of a template or a
+raw cipher. For example, AES on newer x86_64 hardware has the following
+implementations: AES-NI, assembler implementation, or straight C. Now, when
+using the string "aes" with the kernel crypto API, which cipher implementation
+is used? The answer to that question is the priority number assigned to each
+cipher implementation by the kernel crypto API. When a caller uses the string to
+refer to a cipher during initialization of a cipher handle, the kernel crypto
+API looks up all implementations providing an implementation with that name and
+selects the implementation with the highest priority.
+
+Now, a caller may have the need to refer to a specific cipher implementation and
+thus does not want to rely on the priority-based selection. To accommodate this
+scenario, the kernel crypto API allows the cipher implementation to
+register a unique name in addition to common names. When using that unique name,
+a caller is therefore always sure to refer to the intended cipher
+implementation.
+
+The list of available ciphers is given in /proc/crypto. When reading that file,
+all available ciphers with all possible template to raw cipher permutations are
+listed. Each block listed in /proc/crypto contains the following information:
+
+	* name: the generic name of the cipher that is subject to the
+	  priority-based selection -- this name can be used by the cipher
+	  allocation API calls
+
+	* driver: the unique name of the cipher -- this name can be used by the
+	  cipher allocation API calls
+
+	* module: the kernel module providing the cipher implementation (or
+	  "kernel" for statically linked ciphers)
+
+	* priority: the priority value of the cipher implementation
+
+	* refcnt: the reference count of the respective cipher (i.e. the number
+	  of current users of this cipher)
+
+	* selftest: specification whether the self test for the cipher passed
+
+	* type:
+		- blkcipher for symmetric block ciphers
+		- ablkcipher for asymmetric block ciphers
+		- cipher for raw ciphers
+		- shash for symmetric message digest
+		- ahash for asymmetric message digest
+		- aead for AEAD cipher type
+		- compression for compression type transforms
+		- rng for random number generator
+		- givcipher for cipher with associated IV generator
+
+	* blocksize: blocksize of cipher in bytes
+
+	* keysize: key size in bytes
+
+	* ivsize: IV size in bytes
+
+	* seedsize: required size of seed data for random number generator
+
+	* digestsize: output size of the message digest
+
+	* geniv: IV generation type:
+		- eseqiv for encrypted sequence number based IV generation
+		- seqiv for sequence number based IV generation
+		- chainiv for chain iv generation
+		- <builtin> is a marker that the cipher implements IV generation
+
+Note: /proc/crypto only lists ciphers. This file does not specifies registered
+templates. Therefore, this file also does not specify any permutations of
+templates-cipher combinations.
+
+Key sizes
+---------
+
+When allocating a cipher handle, the caller only specifies the cipher type.
+Symmetric ciphers, however, typically support multiple key sizes (e.g. AES-128
+vs. AES-256). These key sizes are determined with the length of the provided
+key. Thus, the kernel crypto API does not provide a separate way to select
+the particular symmetric cipher key size.
+
+Cipher allocation type and masks
+--------------------------------
+
+The different cipher handle allocation functions allow the specification of a
+type and mask flag. Both parameters have the following meaning (and are
+therefore not covered in the subsequent sections).
+
+The type flag specifies the type of the cipher algorithm. The caller usually
+provides a 0 when the caller wants the default handling. Otherwise, the caller
+may provide the following selections which match the the aforementioned cipher
+types:
+
+	* CRYPTO_ALG_TYPE_CIPHER
+	* CRYPTO_ALG_TYPE_COMPRESS
+	* CRYPTO_ALG_TYPE_AEAD
+	* CRYPTO_ALG_TYPE_BLKCIPHER
+	* CRYPTO_ALG_TYPE_ABLKCIPHER
+	* CRYPTO_ALG_TYPE_GIVCIPHER
+	* CRYPTO_ALG_TYPE_DIGEST
+	* CRYPTO_ALG_TYPE_SHASH
+	* CRYPTO_ALG_TYPE_AHASH
+	* CRYPTO_ALG_TYPE_RNG
+	* CRYPTO_ALG_TYPE_PCOMPRESS
+
+The mask flag restricts the type of cipher. The only allowed flag is
+CRYPTO_ALG_ASYNC to restrict the cipher lookup function to asynchronous ciphers.
+Usually, a caller provides a 0 for the mask flag.
+
+Raw cipher API
+==============
+
+#include <linux/crypto.h>
+
+struct crypto_cipher *crypto_alloc_cipher(const char *alg_name, u32 type,
+					  u32 mask)
+
+Allocate a cipher handle for a raw cipher. The returned struct crypto_cipher is
+the cipher handle that is required for any operation with that raw cipher.
+
+alg_name is the name or driver name of the raw cipher.
+
+If an error occurs during this call, PTR_ERR() returns the error code.
+
+
+void crypto_free_cipher(struct crypto_cipher *tfm)
+
+The referenced raw cipher handle is zeroized and subsequently freed.
+
+
+int crypto_has_cipher(const char *alg_name, u32 type, u32 mask)
+
+Return true when the raw cipher with the given alg_name and type/mask flags is
+known to the kernel crypto API. Otherwise return false.
+
+
+int crypto_cipher_blocksize(struct crypto_cipher *tfm)
+
+The block size for the raw cipher referenced with the cipher handle tfm is
+returned.
+
+
+int crypto_cipher_setkey(struct crypto_cipher *tfm, const u8 *key,
+			 unsigned int keylen)
+
+The caller provided key referenced with buffer key and the buffer length of
+keylen is set with the raw cipher referenced by the cipher handle tfm. If the
+setting of the key was successful, the function returns 0. Otherwise a negative
+error code is returned.
+
+
+void crypto_cipher_encrypt_one(struct crypto_cipher *tfm, u8 *dst,
+			       const u8 *src)
+
+The raw cipher referenced with tfm is used to encrypt one block of the plaintext
+data pointed to by src and places the ciphertext data into the dst buffer.
+
+
+void crypto_cipher_decrypt_one(struct crypto_cipher *tfm, u8 *dst,
+			       const u8 *src)
+
+The raw cipher referenced with tfm is used to decrypt one block of the plaintext
+data pointed to by src and places the ciphertext data into the dst buffer.
+
+
+Synchronous block cipher API
+============================
+
+Synchronous calls, have a context in the tfm. But since a single tfm can be used
+in multiple calls and in parallel, this info should not be changeable (unless a
+lock is used). This applies, for example, to the symmetric key. However, the iv
+is changeable, so there is an iv field in blkcipher_tfm structure for
+synchronous blkcipher api. So, its the only state info that can be kept for
+synchronous calls without using a big lock across a tfm.
+
+#include <linux/crypto.h>
+
+struct crypto_blkcipher *crypto_alloc_blkcipher(const char *alg_name, u32 type,
+						u32 mask)
+
+Allocate a cipher handle for a block cipher. The returned struct
+crypto_blkcipher is the cipher handle that is required for any operation with
+that block cipher.
+
+alg_name is the name or driver name of the block cipher.
+
+If an error occurs during this call, PTR_ERR() returns the error code.
+
+
+void crypto_free_blkcipher(struct crypto_blkcipher *tfm)
+
+The referenced block cipher handle is zeroized and subsequently freed.
+
+
+char *crypto_blkcipher_name(struct crypto_blkcipher *tfm)
+
+Obtain the generic name of the block cipher referenced by the handle.
+
+
+int crypto_has_blkcipher(const char *alg_name, u32 type, u32 mask)
+
+Return true when the block cipher with the given alg_name and type/mask flags is
+known to the kernel crypto API. Otherwise return false.
+
+
+unsigned int crypto_blkcipher_ivsize(struct crypto_blkcipher *tfm)
+
+The size of the IV for the block cipher referenced by the cipher handle tfm is
+returned. This IV size may be zero if the cipher does not need an IV.
+
+
+unsigned int crypto_blkcipher_blocksize(struct crypto_blkcipher *tfm)
+
+The block size for the block cipher referenced with the cipher handle tfm is
+returned.
+
+
+int crypto_blkcipher_setkey(struct crypto_blkcipher *tfm, const u8 *key,
+			    unsigned int keylen)
+
+The caller provided key referenced with buffer key and the buffer length of
+keylen is set with the block cipher referenced by the cipher handle tfm. If the
+setting of the key was successful, the function returns 0. Otherwise a negative
+error code is returned.
+
+
+int crypto_blkcipher_encrypt(struct blkcipher_desc *desc,
+			     struct scatterlist *dst,
+			     struct scatterlist *src,
+			     unsigned int nbytes)
+
+The block cipher referenced with desc is used to encrypt nbytes bytes of the
+plaintext data pointed to by the scatter/gather list src and places the
+ciphertext data into the dst scatter/gather list. If the encryption was
+successful, the function returns 0. Otherwise a negative error code is returned.
+
+The caller must fill desc as follows:
+
+	* desc.tfm is filled with the block cipher handle
+	* desc.flags is filled with either CRYPTO_TFM_REQ_MAY_SLEEP or 0
+
+
+int crypto_blkcipher_encrypt_iv(struct blkcipher_desc *desc,
+				struct scatterlist *dst,
+				struct scatterlist *src,
+				unsigned int nbytes)
+
+The block cipher referenced with desc is used to encrypt nbytes bytes of the
+plaintext data pointed to by the scatter/gather list src and places the
+ciphertext data into the dst scatter/gather list. If the encryption was
+successful, the function returns 0. Otherwise a negative error code is returned.
+Note, setting the IV with the API call of crypto_blkcipher_set_iv is not
+required before invoking crypto_blkcipher_encrypt_iv.
+
+The caller must fill desc as follows:
+
+	* desc.tfm is filled with the block cipher handle
+	* desc.info is filled with the IV to be used for the current operation
+	* desc.flags is filled with either CRYPTO_TFM_REQ_MAY_SLEEP or 0
+
+
+int crypto_blkcipher_decrypt(struct blkcipher_desc *desc,
+			     struct scatterlist *dst,
+			     struct scatterlist *src,
+			     unsigned int nbytes)
+
+The block cipher referenced with desc is used to decrypt nbytes bytes of the
+plaintext data pointed to by the scatter/gather list src and places the
+ciphertext data into the dst scatter/gather list. If the decryption was
+successful, the function returns 0. Otherwise a negative error code is returned.
+
+The caller must fill desc as follows:
+
+	* desc.tfm is filled with the block cipher handle
+	* desc.flags is filled with either CRYPTO_TFM_REQ_MAY_SLEEP or 0
+
+
+int crypto_blkcipher_decrypt_iv(struct blkcipher_desc *desc,
+				struct scatterlist *dst,
+				struct scatterlist *src,
+				unsigned int nbytes)
+
+The block cipher referenced with desc is used to decrypt nbytes bytes of the
+plaintext data pointed to by the scatter/gather list src and places the
+ciphertext data into the dst scatter/gather list. If the decryption was
+successful, the function returns 0. Otherwise a negative error code is returned.
+Note, setting the IV with the API call of crypto_blkcipher_set_iv is not
+required before invoking crypto_blkcipher_decrypt_iv.
+
+The caller must fill desc as follows:
+
+	* desc.tfm is filled with the block cipher handle
+	* desc.info is filled with the IV to be used for the current operation
+	* desc.flags is filled with either CRYPTO_TFM_REQ_MAY_SLEEP or 0
+
+
+void crypto_blkcipher_set_iv(struct crypto_blkcipher *tfm, const u8 *src,
+			     unsigned int len)
+
+The caller uses this function to set the IV pointed to by the src buffer of len
+length for the block cipher referenced by the tfm cipher handle.
+
+
+void crypto_blkcipher_get_iv(struct crypto_blkcipher *tfm, u8 *dst,
+			     unsigned int len)
+
+The caller uses this function to obtain the IV set for the block cipher
+referenced by the tfm cipher handle and store it into the user-provided buffer
+dst which has a length of len.
+
+
+Example code
+------------
+
+#include <linux/crypto.h>
+#include <linux/scatterlist.h>	/* scatterlist API */
+#include <linux/random.h>	/* needed for get_random_bytes */
+
+static int test_blkcipher(void)
+{
+	struct crypto_blkcipher *blkcipher = NULL;
+	char *cipher = "cbc(aes)";
+	/* AES 128 */
+	char *key = "\x12\x34\x56\x78\x90\xab\xcd\xef\x12\x34\x56\x78\x90\xab\xcd\xef";
+	char *iv = "\x12\x34\x56\x78\x90\xab\xcd\xef\x12\x34\x56\x78\x90\xab\xcd\xef";
+	unsigned int ivsize = 0;
+	char *scratchpad = NULL; /*
+				  * holds plaintext and ciphertext -- in-place
+				  * encryption
+				  */
+	struct scatterlist sg;
+	struct blkcipher_desc desc;
+	int ret = -EFAULT;
+
+	blkcipher = crypto_alloc_blkcipher(cipher, 0, 0);
+	if (IS_ERR(blkcipher)) {
+		printk("could not allocate blkcipher handle for %s\n", cipher);
+		return -PTR_ERR(blkcipher);
+	}
+
+	if (crypto_blkcipher_setkey(blkcipher, key, strlen(key))) {
+		printk("key could not be set\n");
+		ret = -EAGAIN;
+		goto out;
+	}
+
+	ivsize = crypto_blkcipher_ivsize(blkcipher);
+	if (ivsize) {
+		if (ivsize != strlen(iv))
+			printk("IV length differs from expected length\n");
+		crypto_blkcipher_set_iv(blkcipher, iv, ivsize);
+	}
+
+	scratchpad = kmalloc(crypto_blkcipher_blocksize(blkcipher), GFP_KERNEL);
+	if (!scratchpad) {
+		printk("could not allocate scratchpad for %s\n", cipher);
+		goto out;
+	}
+	/* get some random data that we want to encrypt */
+	get_random_bytes(scratchpad, crypto_blkcipher_blocksize(blkcipher));
+
+	desc.flags = 0;
+	desc.tfm = blkcipher;
+	sg_init_one(&sg, scratchpad, crypto_blkcipher_blocksize(blkcipher));
+
+	/* encrypt data in place */
+	crypto_blkcipher_encrypt(&desc, &sg, &sg,
+				 crypto_blkcipher_blocksize(blkcipher));
+
+	/*
+	 * decrypt data in place
+	 * crypto_blkcipher_decrypt(&desc, &sg, &sg,
+	 *			 crypto_blkcipher_blocksize(blkcipher));
+	 */
+
+	printk("Cipher operation completed\n");
+	return 0;
+
+out:
+	if (blkcipher)
+		crypto_free_blkcipher(blkcipher);
+	if (scratchpad)
+		kzfree(scratchpad);
+	return ret;
+}
+
+
+Asynchronous block cipher API
+=============================
+
+For the synchronous block cipher API, the discussion of the state maintenance
+shows that the state is kept with the tfm handle. However, for asynchronous
+blkcipher calls, context can be in tfm and in the request. Again, a single tfm
+can be used across multiple calls and in parallel. The ablkcipher_request
+structure stores the IV as discussed below and can store additional state info
+in the context field. This would be important for a crypto driver implementer to
+know, because the driver may need to store certain state information. That
+context data field is unused by the kernel crypto API.
+
+#include <linux/crypto.h>
+
+struct crypto_ablkcipher *crypto_alloc_ablkcipher(const char *alg_name,
+						  u32 type, u32 mask)
+
+Allocate a cipher handle for an asynchronous block cipher. The returned struct
+crypto_ablkcipher is the cipher handle that is required for any operation with
+that block cipher.
+
+alg_name is the name or driver name of the block cipher of type "ablkcipher".
+
+If an error occurs during this call, PTR_ERR() returns the error code.
+
+
+void crypto_free_ablkcipher(struct crypto_ablkcipher *tfm)
+
+The referenced block cipher handle is zeroized and subsequently freed.
+
+
+int crypto_has_ablkcipher(const char *alg_name, u32 type,
+			  u32 mask)
+
+Return true when the block cipher with the given alg_name and type/mask flags is
+known to the kernel crypto API. Otherwise return false.
+
+
+unsigned int crypto_ablkcipher_ivsize(struct crypto_ablkcipher *tfm)
+
+The size of the IV for the block cipher referenced by the cipher handle tfm is
+returned. This IV size may be zero if the cipher does not need an IV.
+
+
+unsigned int crypto_ablkcipher_blocksize(struct crypto_ablkcipher *tfm)
+
+The block size for the block cipher referenced with the cipher handle tfm is
+returned.
+
+
+int crypto_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
+			     const u8 *key, unsigned int keylen)
+
+The caller provided key referenced with buffer key and the buffer length of
+keylen is set with the block cipher referenced by the cipher handle tfm. If the
+setting of the key was successful, the function returns 0. Otherwise a negative
+error code is returned.
+
+
+int crypto_ablkcipher_encrypt(struct ablkcipher_request *req)
+
+The block cipher referenced with the ablkcipher_request is used to encrypt
+the data referenced in the ablkcipher_request. Please see below for the
+discussion on creating the ablkcipher_request. If the encryption was
+successful, the function returns 0. Otherwise a negative error code is returned.
+
+
+void *crypto_ablkcipher_ctx(struct crypto_ablkcipher *tfm)
+
+This function accesses the tfm's context to allow the caller to set
+or retrieve the context information. The data type of the pointer must be
+determined by the caller. The kernel crypto API does not use this context
+information. This context information is intended to be used by crypto driver
+implementations and NOT for normal kernel crypto API users.
+
+
+int crypto_ablkcipher_decrypt(struct ablkcipher_request *req)
+
+The block cipher referenced with the ablkcipher_request is used to decrypt
+the data referenced in the ablkcipher_request. Please see below for the
+discussion on creating the ablkcipher_request. If the decryption was
+successful, the function returns 0. Otherwise a negative error code is returned.
+
+
+Generating the ablkcipher_request data structure
+------------------------------------------------
+
+The ablkcipher_request data structure contains all pointers for the asynchronous
+cipher operation. This includes the cipher handle, pointer to plaintext and
+ciphertext, asynchronous callback function, etc.
+
+struct ablkcipher_request *ablkcipher_request_alloc(
+				struct crypto_ablkcipher *tfm, gfp_t gfp)
+
+This function performs the allocation of the data structure ablkcipher_request
+and registers the block cipher handle tfm with the request data structure. The
+gfp parameter requires the caller to specify the memory allocation flag
+(typically GFP_KERNEL). If an error occurs during this call, PTR_ERR() returns
+the error code.
+
+
+void ablkcipher_request_free(struct ablkcipher_request *req)
+
+The referenced ablkcipher_request handle is zeroized and subsequently freed.
+
+
+void ablkcipher_request_set_tfm(struct ablkcipher_request *req,
+				struct crypto_ablkcipher *tfm)
+
+This function allows the caller to set a block cipher handle with the
+ablkcipher_request.
+
+
+void ablkcipher_request_set_callback(struct ablkcipher_request *req,
+				     u32 flags, crypto_completion_t complete,
+				     void *data)
+
+This function sets the callback function which is invoked once the cipher
+operation is completed. The callback function is registered with the
+ablkcipher_request and must comply with the following template:
+
+	void callback_function(struct crypto_async_request *req, int error)
+
+This callback function is to be pointed to using the complete parameter. The
+"flags" parameter may specify zero or more of the following flags:
+
+	* CRYPTO_TFM_REQ_MAY_BACKLOG: the request queue may back log and
+	  increase the wait queue beyond the initial maximum size
+	* CRYPTO_TFM_REQ_MAY_SLEEP: the request processing may sleep
+
+The "data" pointer refers to memory that is not used by the kernel crypto API,
+but provided to the callback function for it to use. Here, the caller can
+provide a reference to memory the callback function can operate on. As the
+callback function is invoked asynchronously to the related functionality, it may
+need to access data structures of the related functionality which can be
+referenced using this pointer. The callback function can access the memory via
+the "data" field in the crypto_async_request structure.
+
+
+void ablkcipher_request_set_crypt(struct ablkcipher_request *req,
+				  struct scatterlist *src,
+				  struct scatterlist *dst,
+				  unsigned int nbytes, void *iv)
+
+By using this call, the caller sets the source and destination scatter /
+gather lists. For encryption, the source is treated as the plaintext and the
+destination is the ciphertext. For a decryption operation, the use is
+reversed: the source is the ciphertext and the destination is the plaintext. The
+number of bytes to process from source is referenced with the "nbytes"
+parameter. The IV is set for the cipher operation using the "iv" parameter.
+
+
+void *ablkcipher_request_ctx(struct ablkcipher_request *req)
+
+This function accesses the request's context to allow the caller to set
+or retrieve the context information. The data type of the pointer must be
+determined by the caller. The kernel crypto API does not use this context
+information. This context information is intended to be used by crypto driver
+implementations and NOT for normal kernel crypto API users.
+
+
+Example code
+------------
+
+The following code is an example for the asynchronous block cipher operation.
+
+#include <linux/crypto.h>
+#include <linux/scatterlist.h>	/* scatterlist API */
+#include <linux/random.h>	/* needed for get_random_bytes */
+
+struct tcrypt_result {
+	struct completion completion;
+	int err;
+};
+
+/* tie all data structures together */
+struct ablkcipher_def {
+	struct scatterlist sg;
+	struct crypto_ablkcipher *tfm;
+	struct ablkcipher_request *req;
+	struct tcrypt_result result;
+};
+
+/* Callback function */
+static void test_ablkcipher_cb(struct crypto_async_request *req, int error)
+{
+	struct tcrypt_result *result = req->data;
+
+	if (error == -EINPROGRESS)
+		return;
+	result->err = error;
+	complete(&result->completion);
+	pr_info("Encryption finished successfully\n");
+}
+
+/* Perform encryption or decryption */
+static unsigned int test_ablkcipher_encdec(struct ablkcipher_def *ablk,
+					   int enc)
+{
+	int rc = 0;
+
+	if (enc)
+		rc = crypto_ablkcipher_encrypt(ablk->req);
+	else
+		rc = crypto_ablkcipher_decrypt(ablk->req);
+
+	switch (rc) {
+	case 0:
+		break;
+	case -EINPROGRESS:
+	case -EBUSY:
+		rc = wait_for_completion_interruptible(
+			&ablk->result.completion);
+		if (!rc && !ablk->result.err) {
+			reinit_completion(&ablk->result.completion);
+			break;
+		}
+	default:
+		pr_info("ablkcipher encrypt returned with %d result %d\n",
+		       rc, ablk->result.err);
+		break;
+	}
+	init_completion(&ablk->result.completion);
+
+	return rc;
+}
+
+/* Initialize and trigger cipher operation */
+static int test_ablkcipher(void)
+{
+	struct ablkcipher_def ablk;
+	struct crypto_ablkcipher *ablkcipher = NULL;
+	struct ablkcipher_request *req = NULL;
+	char *scratchpad = NULL;
+	char *ivdata = NULL;
+	unsigned char key[32];
+	int ret = -EFAULT;
+
+	ablkcipher = crypto_alloc_ablkcipher("cbc-aes-aesni", 0, 0);
+	if (IS_ERR(ablkcipher)) {
+		pr_info("could not allocate ablkcipher handle\n");
+		return -PTR_ERR(ablkcipher);
+	}
+
+	req = ablkcipher_request_alloc(ablkcipher, GFP_KERNEL);
+	if (IS_ERR(req)) {
+		pr_info("could not allocate request queue\n");
+		ret = -PTR_ERR(req);
+		goto out;
+	}
+
+	ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+					test_ablkcipher_cb,
+					&ablk.result);
+
+	/* AES 256 with random key */
+	get_random_bytes(&key, 32);
+	if (crypto_ablkcipher_setkey(ablkcipher, key, 32)) {
+		pr_info("key could not be set\n");
+		ret = -EAGAIN;
+		goto out;
+	}
+
+	/* IV will be random */
+	ivdata = kmalloc(16, GFP_KERNEL);
+	if (!ivdata) {
+		pr_info("could not allocate ivdata\n");
+		goto out;
+	}
+	get_random_bytes(ivdata, 16);
+
+	/* Input data will be random */
+	scratchpad = kmalloc(16, GFP_KERNEL);
+	if (!scratchpad) {
+		pr_info("could not allocate scratchpad\n");
+		goto out;
+	}
+	get_random_bytes(scratchpad, 16);
+
+	ablk.tfm = ablkcipher;
+	ablk.req = req;
+
+	/* We encrypt one block */
+	sg_init_one(&ablk.sg, scratchpad, 16);
+	ablkcipher_request_set_crypt(req, &ablk.sg, &ablk.sg, 16, ivdata);
+	init_completion(&ablk.result.completion);
+
+	/* encrypt data */
+	ret = test_ablkcipher_encdec(&ablk, 1);
+	if (ret)
+		goto out;
+
+	pr_info("Encryption triggered successfully\n");
+
+out:
+	if (ablkcipher)
+		crypto_free_ablkcipher(ablkcipher);
+	if (req)
+		ablkcipher_request_free(req);
+	if (ivdata)
+		kfree(ivdata);
+	if (scratchpad)
+		kfree(scratchpad);
+	return ret;
+}
+
+
+Synchronous message digest API
+==============================
+
+#include <linux/crypto.h>
+
+struct crypto_hash *crypto_alloc_hash(const char *alg_name, u32 type, u32 mask)
+
+Allocate a cipher handle for a hash. The returned struct crypto_hash is the
+cipher handle that is required for any operation with that hash cipher.
+
+alg_name is the name or driver name of the hash of type "shash".
+
+If an error occurs during this call, PTR_ERR() returns the error code.
+
+
+void crypto_free_hash(struct crypto_hash *tfm)
+
+The referenced hash cipher handle is zeroized and subsequently freed.
+
+
+int crypto_hash_blocksize(struct crypto_hash *tfm)
+
+The block size for the hash referenced with the cipher handle tfm is returned.
+
+
+int crypto_hash_digestsize(struct crypto_hash *tfm)
+
+The message digest size for the hash referenced with the cipher handle tfm is
+returned.
+
+
+int crypto_hash_setkey(struct crypto_hash *hash, const u8 *key,
+		       unsigned int keylen)
+
+The caller provided key referenced with buffer key and the buffer length of
+keylen is set with the hash referenced by the cipher handle "hash". The cipher
+handle must point to a keyed hash in order for this function to succeed. If the
+setting of the key was successful, the function returns 0. Otherwise a negative
+error code is returned.
+
+
+
+int crypto_hash_init(struct hash_desc *desc)
+
+The call (re-)initializes the hash referenced by the desc handle. Any
+potentially existing state created by previous operations is discarded.
+
+The caller must fill desc as follows:
+
+	* desc.tfm is filled with the hash cipher handle
+	* desc.flags is filled with either CRYPTO_TFM_REQ_MAY_SLEEP or 0
+
+The function returns 0 on success. In case of an error, it returns the negative
+error value.
+
+
+int crypto_hash_update(struct hash_desc *desc, struct scatterlist *sg, unsigned
+		       int nbytes)
+
+The invocation of crypto_hash_update updates the hash state of the hash cipher
+handle pointed to by desc and the input data pointed to by the scatter/gather
+list sg. Only nbytes of the input data is processed. The function returns 0 on
+success. In case of an error, it returns the negative error value.
+
+
+int crypto_hash_final(struct hash_desc *desc, u8 *out)
+
+With this function, the message digest of the hash state pointed to by desc is
+calculated and placed into the out buffer. The caller must ensure that the out
+buffer has a sufficient size (e.g. by using the crypto_hash_digestsize
+function). The function returns 0 on success. In case of an error, it returns
+the negative error value.
+
+
+int crypto_hash_digest(struct hash_desc *desc, struct scatterlist *sg,
+		       unsigned int nbytes, u8 *out)
+
+This function is a "short-hand" for the function calls of crypto_hash_init,
+crypto_hash_update and crypto_hash_final. The parameters have the same meaning
+as discussed for those separate three functions. The function returns 0 on
+success. In case of an error, it returns the negative error value.
+
+
+Synchronous message digest API with caller-accessible state space
+=================================================================
+
+Considering the discussion of the state maintenance for the block cipher API
+the message digest API is also able to maintain state information for the
+caller. Though, the maintenance of the state is a bit different for the message
+digest API, as both the synchronous and asynchronous message digest APIs
+can store additional context info.
+
+The synchronous message digest API can store user-related context in in its
+shash_desc data structure. Again, this would be important for someone writing a
+crypto driver, with a hash update call where the state can change each time
+update is called.
+
+
+#include <crypto/hash.h>
+
+struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type,
+					u32 mask)
+
+Allocate a cipher handle for a hash. The returned struct crypto_shash is the
+cipher handle that is required for any operation with that hash cipher.
+
+alg_name is the name or driver name of the hash of type "shash".
+
+If an error occurs during this call, PTR_ERR() returns the error code.
+
+
+void crypto_free_shash(struct crypto_shash *tfm)
+
+The referenced hash cipher handle is zeroized and subsequently freed.
+
+
+unsigned int crypto_shash_blocksize(struct crypto_shash *tfm)
+
+The block size for the hash referenced with the cipher handle tfm is returned.
+
+
+unsigned int crypto_shash_digestsize(struct crypto_shash *tfm)
+
+The message digest size for the hash referenced with the cipher handle tfm is
+returned.
+
+
+unsigned int crypto_shash_descsize(struct crypto_shash *tfm)
+
+The size of the operational state the cipher needs during operation is returned
+for the hash referenced with the cipher handle tfm.
+
+
+int crypto_shash_setkey(struct crypto_shash *tfm, const u8 *key,
+			unsigned int keylen);
+
+The caller provided key referenced with buffer key and the buffer length of
+keylen is set with the hash referenced by the cipher handle tfm. This call turns
+the message digest operation into a keyed message digest operation. If the
+setting of the key was successful, the function returns 0. Otherwise a negative
+error code is returned.
+
+
+int crypto_shash_init(struct shash_desc *desc)
+
+The call (re-)initializes the hash referenced by the desc handle. Any
+potentially existing state created by previous operations is discarded.
+
+
+int crypto_shash_update(struct shash_desc *desc, const u8 *data,
+                        unsigned int len)
+
+The invocation of crypto_shash_update updates the hash state of the hash cipher
+handle pointed to by desc (see below for a description of this data structure)
+and the input data pointed to by the "data" pointer. "len" specifies the size of
+"data" in bytes The function returns 0 on success. In case of an error, it
+returns the negative error value.
+
+
+int crypto_shash_final(struct shash_desc *desc, u8 *out)
+
+With this function, the message digest of the hash state pointed to by desc is
+calculated and placed into the out buffer. The caller must ensure that the out
+buffer has a sufficient size (e.g. by using the crypto_shash_digestsize
+function). The function returns 0 on success. In case of an error, it returns
+the negative error value.
+
+
+int crypto_shash_digest(struct shash_desc *desc, const u8 *data,
+			unsigned int len, u8 *out);
+
+This function returns the message digest of the input data pointed to by the
+buffer data that has the length len. The message digest is copied to the out
+buffer that must be allocated by the caller and must have sufficient space (e.g.
+the caller used crypto_shash_digestsize to determine its size). In essence,
+this function is a "short-hand" for the function call combination of
+crypto_shash_update and crypto_shash_final. The function returns 0 on success.
+In case of an error, it returns the negative error value.
+
+The hash cipher handle shash_desc must be allocated by the caller and must have
+sufficient space adjacent to the shash_desc pointer for the state of the hash
+cipher operation. The following code snippet can be used to allocate the memory.
+
+struct sdesc {
+        struct shash_desc shash;
+        char ctx[];
+};
+
+static struct sdesc *init_sdesc(struct crypto_shash *alg)
+{
+	struct sdesc *sdesc;
+	int size;
+
+	size = sizeof(struct shash_desc) + crypto_shash_descsize(alg);
+	sdesc = kmalloc(size, GFP_KERNEL);
+	if (!sdesc)
+		return ERR_PTR(-ENOMEM);
+	sdesc->shash.tfm = alg;
+	sdesc->shash.flags = 0x0;
+	return sdesc;
+}
+
+static int calc_hash(const unsigned char *data, unsigned int datalen,
+		     unsigned char *digest) {
+	struct sdesc *sdesc;
+	int ret;
+
+	sdesc = init_sdesc(hashalg);
+	if (IS_ERR(sdesc)) {
+		pr_info("trusted_key: can't alloc %s\n", hash_alg);
+		return PTR_ERR(sdesc);
+	}
+
+	ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest);
+	kfree(sdesc);
+	return ret;
+}
+
+
+void *shash_desc_ctx(struct shash_desc *desc)
+
+This function accesses the desc's context to allow the caller to set
+or retrieve the context information. The data type of the pointer must be
+determined by the caller. The kernel crypto API does not use this context
+information. This context information is intended to be used by crypto driver
+implementations and NOT for normal kernel crypto API users.
+
+
+int crypto_shash_export(struct shash_desc *desc, void *out)
+
+This function exports the hash state of the cipher handle desc into the
+caller-allocated output buffer out which must have sufficient size (e.g. by
+calling crypto_shash_descsize). The function returns 0 on success. In case of an
+error, it returns the negative error value.
+
+
+int crypto_shash_import(struct shash_desc *desc, const void *in)
+
+This function imports the hash state of the cipher handle desc from the input
+buffer in. The function returns 0 on success. In case of an error, it returns
+the negative error value.
+
+
+Asynchronous message digest API
+===============================
+
+The asynchronous message digest API can store user-related context in in its
+ahash_desc data structure. Again, this would be important for someone writing a
+crypto driver, with  a hash update call where the state can change each time
+update is called.
+
+
+#include <crypto/hash.h>
+
+struct crypto_ahash *crypto_alloc_ahash(const char *alg_name, u32 type,
+					u32 mask)
+
+Allocate a cipher handle for a hash. The returned struct crypto_ahash is the
+cipher handle that is required for any operation with that hash cipher.
+
+alg_name is the name or driver name of the hash of type "ahash".
+
+If an error occurs during this call, PTR_ERR() returns the error code.
+
+
+static inline void crypto_free_ahash(struct crypto_ahash *tfm)
+
+The referenced hash cipher handle is zeroized and subsequently freed.
+
+
+unsigned int crypto_ahash_digestsize(struct crypto_ahash *tfm)
+
+The message digest size for the hash referenced with the cipher handle tfm is
+returned.
+
+
+unsigned int crypto_ahash_reqsize(struct crypto_ahash *tfm)
+
+The size of the operational state the cipher needs during operation is returned
+for the hash referenced with the cipher handle tfm.
+
+
+int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
+			unsigned int keylen)
+
+The caller provided key referenced with buffer key and the buffer length of
+keylen is set with the hash referenced by the cipher handle tfm. This call turns
+the message digest operation into a keyed message digest operation. If the
+setting of the key was successful, the function returns 0. Otherwise a negative
+error code is returned.
+
+
+int crypto_ahash_digest(struct ahash_request *req)
+
+The hash referenced with with the ahash_request is used to calculate the message
+digest of the data referenced in the ahash_request. Please see below for the
+discussion on creating the ahash_request. If the message digest generation was
+successful, the function returns 0. Otherwise a negative error code is returned.
+
+
+int crypto_ahash_init(struct ahash_request *req)
+
+The call (re-)initializes the hash referenced by the ahash_request handle.
+Please see below for the discussion on creating the ahash_request. Any
+potentially existing state created by previous operations is discarded. The
+function returns 0 on success. In case of an error, it returns the negative
+error value.
+
+int crypto_ahash_update(struct ahash_request *req)
+
+The invocation of crypto_hash_update updates the hash state of the ahash_request
+handle pointed to by req. This request handle contains the reference to the
+input data to be added to the message digest via a the scatter/gather list.
+Please see below for the discussion on maintaining the ahash_request data
+structure. The function returns 0 on success. In case of an error, it returns
+the negative error value.
+
+
+int crypto_ahash_final(struct ahash_request *req)
+
+With this function, the message digest of the hash state pointed to by
+ahash_request is calculated and placed into the output buffer referenced in the
+request handle. The function returns 0 on success. In case of an error, it
+returns the negative error value.
+
+
+int crypto_ahash_finup(struct ahash_request *req)
+
+The combination of the crypto_ahash_update and crypto_ahash_final is invoked
+with this function. Therefore the caller only needs one invocation to update and
+finalize the message digest calculation. The function returns 0 on success. In
+case of an error, it returns the negative error value.
+
+
+int crypto_ahash_export(struct ahash_request *req, void *out)
+
+This function exports the hash state of the request handle req into the
+caller-allocated output buffer out which must have sufficient size (e.g. by
+calling crypto_ahash_reqsize). The function returns 0 on success. In case of an
+error, it returns the negative error value.
+
+
+int crypto_ahash_import(struct ahash_request *req, const void *in)
+
+This function imports the hash state of the request handle req from the input
+buffer in. The function returns 0 on success. In case of an error, it returns
+the negative error value.
+
+
+Generating the ahash_request data structure
+-------------------------------------------
+
+The ahash_request data structure contains all pointers for the asynchronous
+cipher operation. This includes the cipher handle, pointer to input data and
+message digest buffer, asynchronous callback function, etc. This data structure
+is conceptually very similar to the ablkcipher_request discussed above.
+
+struct ahash_request *ahash_request_alloc(struct crypto_ahash *tfm, gfp_t gfp)
+
+This function performs the allocation of the data structure ahash_request and
+registers the hash cipher handle tfm with the request data structure. If an
+error occurs during this call, PTR_ERR() returns the error code.
+
+
+void ahash_request_free(struct ahash_request *req)
+
+The referenced ablkcipher_request handle is zeroized and subsequently freed.
+
+
+void ahash_request_set_tfm(struct ahash_request *req, struct crypto_ahash *tfm)
+
+This function allows the caller to set a hash cipher handle with the
+ahash_request.
+
+
+void ahash_request_set_callback(struct ahash_request *req,
+				u32 flags,
+				crypto_completion_t complete,
+				void *data)
+
+This function sets the callback function which is invoked once the cipher
+operation is completed. The callback function is registered with the
+ahash_request and must comply with the following template:
+
+	void callback_function(struct crypto_async_request *req, int error)
+
+This callback function is to be pointed to using the complete parameter. The
+flags parameter may specify zero or more of the following flags:
+
+	* CRYPTO_TFM_REQ_MAY_BACKLOG: the request queue may back log and
+	  increase the wait queue beyond the initial maximum size
+	* CRYPTO_TFM_REQ_MAY_SLEEP: the request processing may sleep
+
+The data pointer refers to memory that is not used by the kernel crypto API, but
+provided to the callback function. Here, the caller can provide a reference to
+memory the callback function can operate on.
+
+
+void ahash_request_set_crypt(struct ahash_request *req,
+			     struct scatterlist *src, u8 *result,
+			     unsigned int nbytes)
+
+By using this call, the caller references the source and destination scatter /
+gather lists. The number of bytes to process from source is referenced with the
+nbytes parameter. The message digest is written to the buffer pointed to by the
+result pointer. The caller must ensure that the buffer has sufficient space by,
+for example, calling crypto_ahash_digestsize.
+
+
+void *ahash_request_ctx(struct ahash_request *req)
+
+This function accesses the request's context to allow the caller to set
+or retrieve the context information. The data type of the pointer must be
+determined by the caller. The kernel crypto API does not use this context
+information. This context information is intended to be used by crypto driver
+implementations and NOT for normal kernel crypto API users.
+
+
+Example code
+------------
+
+The example code given for the asynchronous block cipher operation can be used
+as a template where the ablkcipher function calls are swapped with ahash
+function calls.
+
+
+Random number generation API
+============================
+
+#include <crypto/rng.h>
+
+struct crypto_rng *crypto_alloc_rng(const char *alg_name, u32 type, u32 mask)
+
+Allocate a cipher handle for a random number generator. The returned struct
+crypto_rng is the cipher handle that is required for any operation with that
+random number generator. For all random number generators, this call creates a
+new private copy of the random number generator that does not share a state with
+other instances. The only exception is the "krng" random number generator which
+is a kernel crypto API use case for the get_random_bytes() function of the
+/dev/random driver.
+
+alg_name is the name or driver name of the random number generator.
+
+If an error occurs during this call, PTR_ERR() returns the error code.
+
+
+void crypto_free_rng(struct crypto_rng *tfm)
+
+The referenced random number cipher handle is zeroized and subsequently freed.
+
+
+int crypto_rng_get_bytes(struct crypto_rng *tfm, u8 *rdata, unsigned int dlen)
+
+This function fills the caller-allocated buffer rdata that has the length of
+dlen with random numbers using the random number generator referenced by the tfm
+cipher handle.
+
+The function returns the number of generated random bytes. In case of an error,
+it returns the negative error value.
+
+
+int crypto_rng_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
+
+The reset function completely re-initializes the random number generator
+referenced by the tfm cipher handle by clearing the current state. The new state
+is initialized with the caller provided seed provided in the seed buffer of slen
+length. The provided seed should have the length of the seed size defined for
+the random number generator.
+
+The function returns 0 on success. In case of an error, it returns the negative
+error value.
+
+
+int crypto_rng_seedsize(struct crypto_rng *tfm)
+
+The function returns the seed size for the random number generator referenced by
+the tfm cipher handle.
+
+
+Example code
+------------
+
+static int get_random_numbers(u8 *buf, unsigned int len)
+{
+	struct crypto_rng *rng = NULL;
+	char *drbg = "drbg_nopr_sha256"; /* Hash DRBG with SHA-256, no PR */
+	int ret;
+
+	if (!buf || !len) {
+		pr_debug("No output buffer provided\n");
+		return -EINVAL;
+	}
+
+	rng = crypto_alloc_rng(drbg, 0, 0);
+	if (IS_ERR(rng)) {
+		pr_debug("could not allocate RNG handle for %s\n", drbg);
+		return -PTR_ERR(rng);
+	}
+
+	ret = crypto_rng_get_bytes(rng, buf, len);
+	if (ret < 0)
+		pr_debug("generation of random numbers failed\n");
+	else if (ret == 0)
+		pr_debug("RNG returned no data");
+	else
+		pr_debug("RNG returned %d bytes of data\n", ret);
+
+out:
+	crypto_free_rng(rng);
+	return ret;
+}
+
+AEAD asynchronous cipher API
+============================
+
+The kernel supports Authenticated Encryption with Associated Data. The most
+prominent examples for this type of encryption is GCM and CCM. However, the
+kernel supports other types of AEAD ciphers which are defined with the
+following cipher string:
+
+	authenc(<keyed message digest>, <block cipher>)
+
+For example: authenc(hmac(sha256), cbc(aes))
+
+
+#include <linux/crypto.h>
+
+struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask)
+
+Allocate a cipher handle for the AEAD cipher. The returned struct crypto_aead is
+the cipher handle that is required for any operation with that AEAD cipher.
+
+alg_name is the name or driver name of the hash of type "aead".
+
+If an error occurs during this call, PTR_ERR() returns the error code.
+
+
+void crypto_free_aead(struct crypto_aead *tfm)
+
+The referenced AEAD cipher handle is zeroized and subsequently freed.
+
+
+unsigned int crypto_aead_ivsize(struct crypto_aead *tfm)
+
+The size of the IV for the AEAD cipher referenced by the cipher handle tfm is
+returned. This IV size may be zero if the cipher does not need an IV.
+
+
+unsigned int crypto_aead_authsize(struct crypto_aead *tfm)
+
+The maximum size of the authentication data for the AEAD cipher referenced by
+the cipher handle tfm is returned. The authentication data size may be zero if
+the cipher implements a hard-coded maximum.
+
+
+unsigned int crypto_aead_blocksize(struct crypto_aead *tfm)
+
+The block size for the AEAD cipher referenced with the cipher handle tfm is
+returned.
+
+
+int crypto_aead_setkey(struct crypto_aead *tfm, const u8 *key,
+		       unsigned int keylen)
+
+The caller provided key referenced with buffer key and the buffer length of
+keylen is set with the AEAD cipher referenced by the cipher handle tfm. If the
+setting of the key was successful, the function returns 0. Otherwise a negative
+error code is returned.
+
+
+int crypto_aead_encrypt(struct aead_request *req)
+
+The AEAD cipher referenced with the aead_request is used to encrypt the data
+referenced in the aead_request. Please see below for the discussion on creating
+the aead_request. During the encryption operation, the ciphertext as well as
+the associated data is generated.
+
+The created authentication tag is concatenated with the ciphertext. The
+caller must ensure that sufficient memory is available for the ciphertext and
+the authentication tag.
+
+If the encryption was successful, the function returns 0. Otherwise a negative
+error code is returned.
+
+
+int crypto_aead_decrypt(struct aead_request *req)
+
+The AEAD cipher referenced with the aead_request is used to decrypt the data
+referenced in the aead_request. Please see below for the discussion on creating
+the aead_request. If the encryption was successful, the function returns 0.
+Otherwise a negative error code is returned.
+
+The caller must concatenate the ciphertext followed by the authentication tag.
+
+The AEAD cipher operation performs the authentication of the data during the
+decryption operation. Therefore, the crypto_aead_decrypt returns the error of
+-EBADMSG if the authentication of the ciphertext was unsuccessful (i.e. the
+integrity of the ciphertext or the associated data was violated).
+
+
+int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
+
+Set the Authentication Tag size. AEAD requires an authentication tag (or MAC)
+in addition to the associated data. The authentication tag is appended
+to the ciphertext. If the setting of the authentication data size was
+successful, the function returns 0. Otherwise a negative error code is returned
+(e.g. set authentication data size is larger than maximum authentication data
+size).
+
+
+Generating the aead_request data structure
+------------------------------------------
+
+The aead_request data structure contains all pointers for the asynchronous
+cipher operation. This includes the cipher handle, pointer to plaintext and
+ciphertext, associated data, asynchronous callback function, etc.
+
+struct aead_request *aead_request_alloc(struct crypto_aead *tfm, gfp_t gfp)
+
+This function performs the allocation of the data structure aead_request
+and registers the AEAD cipher handle tfm with the request data structure. The
+gfp parameter requires the caller to specify the memory allocation flag
+(typically GFP_KERNEL). If an error occurs during this call, PTR_ERR() returns
+the error code.
+
+
+void aead_request_free(struct aead_request *req)
+
+The referenced aead_request handle is zeroized and subsequently freed.
+
+
+void aead_request_set_tfm(struct aead_request *req, struct crypto_aead *tfm)
+
+This function allows the caller to set a block cipher handle with the
+aead_request.
+
+
+void aead_request_set_callback(struct aead_request *req, u32 flags,
+			       crypto_completion_t complete, void *data)
+
+This function sets the callback function which is invoked once the cipher
+operation is completed. The callback function is registered with the
+ablkcipher_request and must comply with the following template:
+
+	void callback_function(struct crypto_async_request *req, int error)
+
+This callback function is to be pointed to using the complete parameter. The
+"flags" parameter may specify zero or more of the following flags:
+
+	* CRYPTO_TFM_REQ_MAY_BACKLOG: the request queue may back log and
+	  increase the wait queue beyond the initial maximum size
+	* CRYPTO_TFM_REQ_MAY_SLEEP: the request processing may sleep
+
+The "data" pointer refers to memory that is not used by the kernel crypto API,
+but provided to the callback function for it to use. Here, the caller can
+provide a reference to memory the callback function can operate on. As the
+callback function is invoked asynchronously to the related functionality, it may
+need to access data structures of the related functionality which can be
+referenced using this pointer. The callback function can access the memory via
+the "data" field in the crypto_async_request structure.
+
+
+void aead_request_set_crypt(struct aead_request *req,
+			    struct scatterlist *src,
+			    struct scatterlist *dst,
+			    unsigned int cryptlen, u8 *iv)
+
+By using this call, the caller sets the source and destination scatter /
+gather lists. For encryption, the source is treated as the plaintext and the
+destination is the ciphertext. For a decryption operation, the use is
+reversed: the source is the ciphertext and the destination is the plaintext. The
+number of bytes to process from source is referenced with the "cryptlen"
+parameter. The IV is set for the cipher operation using the "iv" parameter.
+
+Important note: AEAD requires an authentication tag (MAC). For decryption, the
+caller must concatenate the ciphertext followed by the authentication tag and
+provide the entire data stream to the decryption operation (i.e. the data length
+used for the initialization of the scatterlist and the data length for the
+decryption operation is identical). For encryption, however, the authentication
+tag is created while encrypting the data. The destination buffer must hold
+sufficient space for the ciphertext and the authentication tag while the
+encryption invocation must only point to the plaintext data size. The following
+code snippet should illustrate that:
+
+/*
+ * sg is the pointer to plaintext and will hold the cipher text
+ * authsize is the size of the authentication tag
+ * enc is 1 for encryption, 0 for decryption
+ * ptbuf is the buffer with the plaintext
+ * ptbuflen is the plaintext buffer size
+ */
+buffer = kmalloc(ptbuflen + (enc ? authsize : 0));
+memcpy(buffer, ptbuf, ptbuflen);
+sg_init_one(&sg, buffer, ptbuflen + (enc ? authsize : 0));
+aead_request_set_crypt(req, &sg, &sg, ptbuflen, iv);
+
+
+void aead_request_set_assoc(struct aead_request *req,
+			    struct scatterlist *assoc, unsigned int assoclen)
+
+The scatter / gather list "assoc" points to the associated data and "assoclen"
+specifies the size of the associated data.
+
+For encryption, the pointer must reference memory that is filled with the
+associated data. That associated data must be transported to the entity
+performing the AEAD decryption along with the ciphertext. For decryption, this
+function call allows the caller to set the pointer to the associated data for
+the integrity verification.
+
+
+Example code
+------------
+
+The example code provided for the asynchronous block cipher operation applies
+here as well. The only difference is that for the AEAD operation, the
+aead_request_set_assoc function must be used to set the associated data before
+performing the encryption or decryption operation.
+
+The second deviation from the asynchronous block cipher operation is that the
+caller should explicitly check for -EBADMSG of the crypto_aead_decrypt
+invocation to catch authentication errors.
+
+
+User space API
+==============
+
+The kernel crypto API is accessible from user space. Currently, the following
+ciphers are accessible:
+
+	* Message digest including keyed message digest
+
+	* Symmetric ciphers
+
+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.
+
+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.
+
+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_nmae = "sha1" /* this is the cipher name */
+};
+
+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 read() 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.
+
+
+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 */
+};
+
+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 read() 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 the as many blocks are returned that fit into that
+output buffer size.
+
+User space API example
+----------------------
+
+Compile the following code with the gcc flags of "-Wextra -Wall -pedantic".
+
+/*
+ * Code from cryptsetup version 1.6.4 used as a basis
+ */
+
+#include <stdio.h>
+
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <linux/if_alg.h>
+#include <stdint.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifndef AF_ALG
+#define AF_ALG 38
+#endif
+#ifndef SOL_ALG
+#define SOL_ALG 279
+#endif
+
+/************************************************************
+ * Application interfaces
+ ************************************************************/
+
+/* Cipher handle */
+struct kcapi_handle {
+	int tfmfd;
+	int opfd;
+};
+
+/************************************************************
+ * Internal logic
+ ************************************************************/
+
+/* The in/out should be aligned to page boundary */
+static int _kcapi_cipher_crypt(struct kcapi_handle *handle,
+			       const unsigned char *in, size_t inlen,
+			       unsigned char *out, size_t outlen,
+			       const unsigned char *iv, size_t ivlen,
+			       uint32_t enc)
+{
+	int r = 0;
+	ssize_t ret;
+	struct af_alg_iv *alg_iv;
+	struct cmsghdr *header;
+	uint32_t *type;
+	struct iovec iov;
+	int iv_msg_size = iv ? CMSG_SPACE(sizeof(*alg_iv) + ivlen) : 0;
+	char *buffer = NULL;
+	unsigned int bufferlen = CMSG_SPACE(sizeof(*type)) + iv_msg_size;
+	struct msghdr msg;
+
+	if (!in || !out || !inlen || !outlen)
+		return -EINVAL;
+
+	if ((!iv && ivlen) || (iv && !ivlen))
+		return -EINVAL;
+
+	buffer = calloc(1, bufferlen);
+	if (!buffer)
+		return -ENOMEM;
+
+	iov.iov_base = (void*)(uintptr_t)in;
+	iov.iov_len = inlen;
+	msg.msg_control = buffer;
+	msg.msg_controllen = bufferlen;
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+
+	/* encrypt/decrypt operation */
+	header = CMSG_FIRSTHDR(&msg);
+	header->cmsg_level = SOL_ALG;
+	header->cmsg_type = ALG_SET_OP;
+	header->cmsg_len = CMSG_LEN(sizeof(*type));
+	type = (void*)CMSG_DATA(header);
+	*type = enc;
+
+	/* set IV */
+	if (iv) {
+		header = CMSG_NXTHDR(&msg, header);
+		header->cmsg_level = SOL_ALG;
+		header->cmsg_type = ALG_SET_IV;
+		header->cmsg_len = iv_msg_size;
+		alg_iv = (void*)CMSG_DATA(header);
+		alg_iv->ivlen = ivlen;
+		memcpy(alg_iv->iv, iv, ivlen);
+	}
+
+	ret = sendmsg(handle->opfd, &msg, 0);
+	if (ret != (ssize_t)inlen) {
+		r = -EIO;
+		goto bad;
+	}
+
+	ret = read(handle->opfd, out, outlen);
+	if (ret != (ssize_t)outlen)
+		r = -EIO;
+bad:
+	memset(buffer, 0, bufferlen);
+	free(buffer);
+	return r;
+}
+
+
+/************************************************************
+ * API to application
+ ************************************************************/
+
+/*
+ * Initialization of a cipher handle and establishing the connection to
+ * the kernel
+ *
+ * @handle cipher handle filled during the call - output
+ * @type cipher type, one of the following - input:
+ *	 "hash" for message digests (including keyed message digests)
+ *	 "skcipher" for symmetric ciphers
+ * @ciphername kernel crypto API cipher name as specified in
+ *	       /proc/crypto - input
+ *
+ * return: 0 upon success
+ *	   < 0 in case of error
+ *		ENOENT - algorithm not available
+ *		ENOTSUP - AF_ALG family not available
+ *		EINVAL - accept syscall failed
+ */
+int kcapi_cipher_init(struct kcapi_handle *handle,
+		      const char *type, const char *ciphername)
+{
+	struct sockaddr_alg sa;
+
+	memset(&sa, 0, sizeof(sa));
+	sa.salg_family = AF_ALG;
+	snprintf((char *)sa.salg_type, sizeof(sa.salg_type),"%s", type);
+	snprintf((char *)sa.salg_name, sizeof(sa.salg_name),"%s", ciphername);
+
+	handle->tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
+	if (handle->tfmfd == -1)
+		return -ENOTSUP;
+
+	if (bind(handle->tfmfd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
+		close(handle->tfmfd);
+		handle->tfmfd = -1;
+		return -ENOENT;
+	}
+
+	handle->opfd = accept(handle->tfmfd, NULL, 0);
+	if (handle->opfd == -1) {
+		close(handle->tfmfd);
+		handle->tfmfd = -1;
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Close the cipher handle and release resources
+ *
+ * @handle cipher handle to release - input
+ *
+ * return: 0 upon success
+ */
+int kcapi_cipher_destory(struct kcapi_handle *handle)
+{
+	if (handle->tfmfd != -1)
+		close(handle->tfmfd);
+	if (handle->opfd != -1)
+		close(handle->opfd);
+	return 0;
+}
+
+
+/*
+ * Set the key for the cipher handle
+ *
+ * This call is applicable for keyed message digests and symmetric ciphers.
+ *
+ * @handle cipher handle - input
+ * @key key buffer - input
+ * @keylen length of key buffer - input
+ *
+ * return: 0 upon success
+ *	   < 0 in case of error
+ */
+int kcapi_cipher_setkey(struct kcapi_handle *handle,
+			const unsigned char *key, size_t keylen)
+{
+	if (setsockopt(handle->tfmfd, SOL_ALG, ALG_SET_KEY,
+		       key, keylen) == -1)
+		return -EINVAL;
+
+	return 0;
+}
+
+/*
+ * Message digest update function
+ *
+ * @handle cipher handle - input
+ * @buffer holding the data to add to the message digest - input
+ * @len buffer length - input
+ *
+ * return: 0 upon success
+ *	   < 0 in case of error
+ */
+int kcapi_md_update(struct kcapi_handle *handle,
+		    const unsigned char *buffer, size_t len)
+{
+	ssize_t r;
+
+	r = send(handle->opfd, buffer, len, MSG_MORE);
+	if (r < 0 || (size_t)r < len)
+		return -EIO;
+
+	return 0;
+}
+
+/*
+ * Message digest finalization function
+ *
+ * @handle cipher handle - input
+ * @buffer filled with the message digest - output
+ * @len buffer length - input
+ *
+ * return: 0 upon success
+ *	   < 0 in case of error
+ *		EIO - data cannot be obtained
+ *		ENOMEM - buffer is too small for the complete message digest,
+ *			 the buffer is filled with the truncated message digest
+ */
+
+int kcapi_md_final(struct kcapi_handle *handle,
+		   unsigned char *buffer, size_t len)
+{
+	ssize_t r;
+	struct iovec iov;
+	struct msghdr msg;
+
+	iov.iov_base = (void*)(uintptr_t)buffer;
+	iov.iov_len = len;
+	msg.msg_name = NULL;
+	msg.msg_namelen = 0;
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+	msg.msg_control = NULL;
+	msg.msg_controllen = 0;
+
+	r = recvmsg(handle->opfd, &msg, 0);
+	if (r < 0)
+		return -EIO;
+	if (msg.msg_flags & MSG_TRUNC)
+		return -ENOMEM;
+
+	return 0;
+}
+
+/*
+ * Encrypt data
+ *
+ * @handle cipher handle - input
+ * @in plaintext data buffer - input
+ * @inlen length of in buffer - input
+ * @out ciphertext data buffer - output
+ * @outlen length of out buffer - input
+ * @iv buffer holding the IV (may be NULL if IV is not needed) - input
+ * @ivlen length of iv (should be zero if iv is NULL) - input
+ *
+ * return: 0 upon success
+ *	   < 0 in case of error
+ */
+int kcapi_cipher_encrypt(struct kcapi_handle *handle,
+			 const unsigned char *in, size_t inlen,
+			 unsigned char *out, size_t outlen,
+			 const unsigned char *iv, size_t ivlen)
+{
+	return _kcapi_cipher_crypt(handle, in, inlen, out, outlen,
+				   iv, ivlen, ALG_OP_ENCRYPT);
+}
+
+/*
+ * Decrypt data
+ *
+ * @handle cipher handle - input
+ * @in ciphertext data buffer - input
+ * @inlen length of in buffer - input
+ * @out plaintext data buffer - output
+ * @outlen length of out buffer - input
+ * @iv buffer holding the IV (may be NULL if IV is not needed) - input
+ * @ivlen length of iv (should be zero if iv is NULL) - input
+ *
+ * return: 0 upon success
+ *	   < 0 in case of error
+ */
+int kcapi_cipher_decrypt(struct kcapi_handle *handle,
+			 const unsigned char *in, size_t inlen,
+			 unsigned char *out, size_t outlen,
+			 const unsigned char *iv, size_t ivlen)
+{
+	return _kcapi_cipher_crypt(handle, in, inlen, out, outlen,
+				   iv, ivlen, ALG_OP_DECRYPT);
+}
+
+/************************************************************
+ * Application requiring cryptographic services
+ ************************************************************/
+
+static char hex_char_map_l[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+				 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+static char hex_char_map_u[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+				 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+static char hex_char(unsigned int bin, int u)
+{
+	if (bin < sizeof(hex_char_map_l))
+		return (u) ? hex_char_map_u[bin] : hex_char_map_l[bin];
+	return 'X';
+}
+
+/*
+ * Convert binary string into hex representation
+ * @bin input buffer with binary data
+ * @binlen length of bin
+ * @hex output buffer to store hex data
+ * @hexlen length of already allocated hex buffer (should be at least
+ *	   twice binlen -- if not, only a fraction of binlen is converted)
+ * @u case of hex characters (0=>lower case, 1=>upper case)
+ */
+static void bin2hex(const unsigned char *bin, size_t binlen,
+		    char *hex, size_t hexlen, int u)
+{
+	size_t i = 0;
+	size_t chars = (binlen > (hexlen / 2)) ? (hexlen / 2) : binlen;
+
+	for (i = 0; i < chars; i++) {
+		hex[(i*2)] = hex_char((bin[i] >> 4), u);
+		hex[((i*2)+1)] = hex_char((bin[i] & 0x0f), u);
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	struct kcapi_handle handle;
+#define BUFLEN 32
+	unsigned char inbuf[BUFLEN];
+#define IVLEN 16
+	unsigned char ivbuf[IVLEN];
+	unsigned char outbuf[BUFLEN];
+	unsigned char outbuf2[BUFLEN];
+	char hexbuf[BUFLEN * 2 + 1];
+
+	(void)argc;
+	(void)argv;
+
+	/*
+	 * Calculate a message digest
+	 */
+	if (kcapi_cipher_init(&handle, "hash", "sha256")) {
+		printf("Allocation of hash failed\n");
+		return(1);
+	}
+	memcpy(inbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
+		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+		      "\x00\x01\x02\x03\x04\x05\x06\x07"
+		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", BUFLEN);
+	if (kcapi_md_update(&handle, inbuf, BUFLEN)) {
+		printf("Hash update of buffer failed\n");
+		return(1);
+	}
+	if (kcapi_md_final(&handle, outbuf, BUFLEN)) {
+		printf("Hash final failed\n");
+		return(1);
+	}
+	kcapi_cipher_destory(&handle);
+	memset(hexbuf, 0, BUFLEN * 2 + 1);
+	bin2hex(outbuf, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
+	printf("Calculated hash %s\n", hexbuf);
+
+	/*
+	 * Calculate a keyed message digest
+	 */
+	if (kcapi_cipher_init(&handle, "hash", "hmac(sha256)")) {
+		printf("Allocation of HMAC failed\n");
+		return(1);
+	}
+	memcpy(inbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
+		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+		      "\x00\x01\x02\x03\x04\x05\x06\x07"
+		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", BUFLEN);
+	if (kcapi_cipher_setkey(&handle, inbuf, BUFLEN)) {
+		printf("HMAC setkey failed\n");
+		return(1);
+	}
+	if (kcapi_md_update(&handle, inbuf, BUFLEN)) {
+		printf("HMAC update of buffer failed\n");
+		return(1);
+	}
+	if (kcapi_md_final(&handle, outbuf, BUFLEN)) {
+		printf("HMAC final failed\n");
+		return(1);
+	}
+	kcapi_cipher_destory(&handle);
+	memset(hexbuf, 0, BUFLEN * 2 + 1);
+	bin2hex(outbuf, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
+	printf("Calculated hmac %s\n", hexbuf);
+
+	/*
+	 * Encrypt data
+	 */
+	if (kcapi_cipher_init(&handle, "skcipher", "cbc(aes)")) {
+		printf("Allocation of cipher failed\n");
+		return(1);
+	}
+	memcpy(inbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
+		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+		      "\x00\x01\x02\x03\x04\x05\x06\x07"
+		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", BUFLEN);
+	if (kcapi_cipher_setkey(&handle, inbuf, BUFLEN)) {
+		printf("AES setkey failed\n");
+		return(1);
+	}
+	memcpy(ivbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
+		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", IVLEN);
+	if (kcapi_cipher_encrypt(&handle, inbuf, BUFLEN,
+				 outbuf, BUFLEN, ivbuf, IVLEN)) {
+		printf("Encryption buffer failed\n");
+		return(1);
+	}
+	memset(hexbuf, 0, BUFLEN * 2 + 1);
+	bin2hex(outbuf, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
+	printf("Encrypted data %s\n", hexbuf);
+
+	/*
+	 * Decrypt previously encrypted data
+	 */
+	if (kcapi_cipher_decrypt(&handle, outbuf, BUFLEN,
+				 outbuf2, BUFLEN, ivbuf, IVLEN)) {
+		printf("Decryption buffer failed\n");
+		return(1);
+	}
+	kcapi_cipher_destory(&handle);
+	memset(hexbuf, 0, BUFLEN * 2 + 1);
+	bin2hex(outbuf2, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
+	printf("Decrypted data %s\n", hexbuf);
+	if (!memcmp(inbuf, outbuf2, BUFLEN))
+		printf("Decrypted data match original plaintext as expected\n");
+	else
+		printf("FAILURE: Decrypted data does not match original plaintext\n");
+
+	return 0;
+}
+
+License of code
+===============
+/*
+ * Copyright (C) 2014, Stephan Mueller <smueller@chronox.de>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL2 are
+ * required INSTEAD OF the above restrictions.  (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
-- 
1.9.3



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH] kernel crypto API interface specification
  2014-10-14 19:46 [PATCH] kernel crypto API interface specification Stephan Mueller
@ 2014-10-14 20:00 ` Stephan Mueller
  2014-10-15 17:58 ` Jason Cooper
  2014-10-16 13:10 ` Herbert Xu
  2 siblings, 0 replies; 14+ messages in thread
From: Stephan Mueller @ 2014-10-14 20:00 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller; +Cc: linux-crypto, linux-kernel

Am Dienstag, 14. Oktober 2014, 21:46:50 schrieb Stephan Mueller:

Hi,

> The update adds a complete interface documentation of the kernel crypto
> API. All cipher types supported by the kernel crypto API are documented.
> 
> In addition, kernel and user space example code is provided. The sample
> code covers synchronous and asynchronous cipher operation, random
> number generation and performing hashing as well as encryption and
> decryption in user space.

I was not sure whether to cover the explanation of the API in a separate 
document or whether to add the function documentation to 
include/linux/crypto.h.

With the first attempt of the documentation, I applied the least invasive 
approach. If it is requested, I would modify the patch such that appropriate 
source code comments to the functions in the header file are added.

-- 
Ciao
Stephan

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] kernel crypto API interface specification
  2014-10-14 19:46 [PATCH] kernel crypto API interface specification Stephan Mueller
  2014-10-14 20:00 ` Stephan Mueller
@ 2014-10-15 17:58 ` Jason Cooper
  2014-10-16  7:19   ` Stephan Mueller
  2014-10-16 13:10 ` Herbert Xu
  2 siblings, 1 reply; 14+ messages in thread
From: Jason Cooper @ 2014-10-15 17:58 UTC (permalink / raw)
  To: Stephan Mueller; +Cc: Herbert Xu, David S. Miller, linux-crypto, linux-kernel

Stephan,

Wow.  This is very thorough.  Herbert and others will be making the
final call on this, but if I may make a suggestion:

On Tue, Oct 14, 2014 at 09:46:50PM +0200, Stephan Mueller wrote:
> The update adds a complete interface documentation of the kernel crypto
> API. All cipher types supported by the kernel crypto API are documented.
> 
> In addition, kernel and user space example code is provided. The sample
> code covers synchronous and asynchronous cipher operation, random
> number generation and performing hashing as well as encryption and
> decryption in user space.

This really needs to be split into at least two pieces.  The kernel and
the userspace API.  I'd venture to say the userspace API portion of this
document is almost ready.  But I'm not certain that the kernel
interfaces are best described in a specification.

APIs within the kernel are intentionally not nailed down and are very
fluid.  Any attempt to spell them out in a document would mean either a)
the document would be out of date quickly, or b) the maintainer now has
to ask for changes to the docs every time a patch with a kernel API
change comes in.  Neither scenario is good. :-(

We certainly don't want to lose all of the effort you've put into
grokking the API, so we need to find a maintainable place to add it.  I
personally think adding comments above the respective function
blocks would work well.

The examples (kernel API) are another matter entirely.  Examples that
aren't up-to-date and usable as a template aren't helpful to anyone.
Some would even say detrimental.  And since example code isn't actually
*used* in the real world, it would be an extra burden keeping it up to
date.  I think these could best be used as a reference to compare all of
the current users to.  Anything not up to par would generate a patch.
The best examples should be the current users in the kernel.

> Signed-off-by: Stephan Mueller <smueller@chronox.de>
> ---
>  Documentation/crypto/crypto-API-spec.txt | 2110 ++++++++++++++++++++++++++++++
>  1 file changed, 2110 insertions(+)
>  create mode 100644 Documentation/crypto/crypto-API-spec.txt
> 
> diff --git a/Documentation/crypto/crypto-API-spec.txt b/Documentation/crypto/crypto-API-spec.txt
> new file mode 100644
> index 0000000..027fd4f
> --- /dev/null
> +++ b/Documentation/crypto/crypto-API-spec.txt
> @@ -0,0 +1,2110 @@

[snip detailed explanation of current kernel API]

> +User space API
> +==============
> +
> +The kernel crypto API is accessible from user space. Currently, the following
> +ciphers are accessible:
> +
> +	* Message digest including keyed message digest
> +
> +	* Symmetric ciphers
> +
> +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.

Perhaps a reference here to the final location of the kernel API
explanations?

> +
> +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.
> +
> +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_nmae = "sha1" /* this is the cipher name */
> +};
> +
> +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 read() 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.

What happens if this is omitted?

> +
> +
> +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 */
> +};
> +
> +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 read() 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 the as many blocks are returned that fit into that

...only as many blocks...

> +output buffer size.
> +
> +User space API example
> +----------------------
> +
> +Compile the following code with the gcc flags of "-Wextra -Wall -pedantic".
> +
> +/*
> + * Code from cryptsetup version 1.6.4 used as a basis
> + */

Could you specify the git commit and file from cryptsetup?  This way, if
the this example becomes out of date, users could easily jump to the
newest version of working code used in the real world.

> +
> +#include <stdio.h>
> +
> +#include <unistd.h>
> +#include <sys/socket.h>
> +#include <sys/types.h>
> +#include <linux/if_alg.h>
> +#include <stdint.h>
> +#include <errno.h>
> +#include <string.h>
> +#include <stdlib.h>
> +
> +#ifndef AF_ALG
> +#define AF_ALG 38
> +#endif
> +#ifndef SOL_ALG
> +#define SOL_ALG 279
> +#endif
> +
> +/************************************************************
> + * Application interfaces
> + ************************************************************/
> +
> +/* Cipher handle */
> +struct kcapi_handle {
> +	int tfmfd;
> +	int opfd;
> +};
> +
> +/************************************************************
> + * Internal logic
> + ************************************************************/
> +
> +/* The in/out should be aligned to page boundary */
> +static int _kcapi_cipher_crypt(struct kcapi_handle *handle,
> +			       const unsigned char *in, size_t inlen,
> +			       unsigned char *out, size_t outlen,
> +			       const unsigned char *iv, size_t ivlen,
> +			       uint32_t enc)
> +{
> +	int r = 0;
> +	ssize_t ret;
> +	struct af_alg_iv *alg_iv;
> +	struct cmsghdr *header;
> +	uint32_t *type;
> +	struct iovec iov;
> +	int iv_msg_size = iv ? CMSG_SPACE(sizeof(*alg_iv) + ivlen) : 0;
> +	char *buffer = NULL;
> +	unsigned int bufferlen = CMSG_SPACE(sizeof(*type)) + iv_msg_size;
> +	struct msghdr msg;
> +
> +	if (!in || !out || !inlen || !outlen)
> +		return -EINVAL;
> +
> +	if ((!iv && ivlen) || (iv && !ivlen))
> +		return -EINVAL;
> +
> +	buffer = calloc(1, bufferlen);
> +	if (!buffer)
> +		return -ENOMEM;
> +
> +	iov.iov_base = (void*)(uintptr_t)in;
> +	iov.iov_len = inlen;
> +	msg.msg_control = buffer;
> +	msg.msg_controllen = bufferlen;
> +	msg.msg_iov = &iov;
> +	msg.msg_iovlen = 1;
> +
> +	/* encrypt/decrypt operation */
> +	header = CMSG_FIRSTHDR(&msg);
> +	header->cmsg_level = SOL_ALG;
> +	header->cmsg_type = ALG_SET_OP;
> +	header->cmsg_len = CMSG_LEN(sizeof(*type));
> +	type = (void*)CMSG_DATA(header);
> +	*type = enc;
> +
> +	/* set IV */
> +	if (iv) {
> +		header = CMSG_NXTHDR(&msg, header);
> +		header->cmsg_level = SOL_ALG;
> +		header->cmsg_type = ALG_SET_IV;
> +		header->cmsg_len = iv_msg_size;
> +		alg_iv = (void*)CMSG_DATA(header);
> +		alg_iv->ivlen = ivlen;
> +		memcpy(alg_iv->iv, iv, ivlen);
> +	}
> +
> +	ret = sendmsg(handle->opfd, &msg, 0);
> +	if (ret != (ssize_t)inlen) {
> +		r = -EIO;
> +		goto bad;
> +	}
> +
> +	ret = read(handle->opfd, out, outlen);
> +	if (ret != (ssize_t)outlen)
> +		r = -EIO;
> +bad:
> +	memset(buffer, 0, bufferlen);

Not related to this patch, but you should take a look at:

  http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html
  http://www.daemonology.net/blog/2014-09-06-zeroing-buffers-is-insufficient.html


> +	free(buffer);
> +	return r;
> +}
> +
> +
> +/************************************************************
> + * API to application
> + ************************************************************/
> +
> +/*
> + * Initialization of a cipher handle and establishing the connection to
> + * the kernel
> + *
> + * @handle cipher handle filled during the call - output
> + * @type cipher type, one of the following - input:
> + *	 "hash" for message digests (including keyed message digests)
> + *	 "skcipher" for symmetric ciphers
> + * @ciphername kernel crypto API cipher name as specified in
> + *	       /proc/crypto - input
> + *
> + * return: 0 upon success
> + *	   < 0 in case of error
> + *		ENOENT - algorithm not available
> + *		ENOTSUP - AF_ALG family not available
> + *		EINVAL - accept syscall failed
> + */
> +int kcapi_cipher_init(struct kcapi_handle *handle,
> +		      const char *type, const char *ciphername)
> +{
> +	struct sockaddr_alg sa;
> +
> +	memset(&sa, 0, sizeof(sa));
> +	sa.salg_family = AF_ALG;
> +	snprintf((char *)sa.salg_type, sizeof(sa.salg_type),"%s", type);
> +	snprintf((char *)sa.salg_name, sizeof(sa.salg_name),"%s", ciphername);
> +
> +	handle->tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
> +	if (handle->tfmfd == -1)
> +		return -ENOTSUP;
> +
> +	if (bind(handle->tfmfd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
> +		close(handle->tfmfd);
> +		handle->tfmfd = -1;
> +		return -ENOENT;
> +	}
> +
> +	handle->opfd = accept(handle->tfmfd, NULL, 0);
> +	if (handle->opfd == -1) {
> +		close(handle->tfmfd);
> +		handle->tfmfd = -1;
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +/*
> + * Close the cipher handle and release resources
> + *
> + * @handle cipher handle to release - input
> + *
> + * return: 0 upon success
> + */
> +int kcapi_cipher_destory(struct kcapi_handle *handle)
> +{
> +	if (handle->tfmfd != -1)
> +		close(handle->tfmfd);
> +	if (handle->opfd != -1)
> +		close(handle->opfd);
> +	return 0;
> +}
> +
> +
> +/*
> + * Set the key for the cipher handle
> + *
> + * This call is applicable for keyed message digests and symmetric ciphers.
> + *
> + * @handle cipher handle - input
> + * @key key buffer - input
> + * @keylen length of key buffer - input
> + *
> + * return: 0 upon success
> + *	   < 0 in case of error
> + */
> +int kcapi_cipher_setkey(struct kcapi_handle *handle,
> +			const unsigned char *key, size_t keylen)
> +{
> +	if (setsockopt(handle->tfmfd, SOL_ALG, ALG_SET_KEY,
> +		       key, keylen) == -1)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +/*
> + * Message digest update function
> + *
> + * @handle cipher handle - input
> + * @buffer holding the data to add to the message digest - input
> + * @len buffer length - input
> + *
> + * return: 0 upon success
> + *	   < 0 in case of error
> + */
> +int kcapi_md_update(struct kcapi_handle *handle,
> +		    const unsigned char *buffer, size_t len)
> +{
> +	ssize_t r;
> +
> +	r = send(handle->opfd, buffer, len, MSG_MORE);
> +	if (r < 0 || (size_t)r < len)
> +		return -EIO;
> +
> +	return 0;
> +}
> +
> +/*
> + * Message digest finalization function
> + *
> + * @handle cipher handle - input
> + * @buffer filled with the message digest - output
> + * @len buffer length - input
> + *
> + * return: 0 upon success
> + *	   < 0 in case of error
> + *		EIO - data cannot be obtained
> + *		ENOMEM - buffer is too small for the complete message digest,
> + *			 the buffer is filled with the truncated message digest
> + */
> +
> +int kcapi_md_final(struct kcapi_handle *handle,
> +		   unsigned char *buffer, size_t len)
> +{
> +	ssize_t r;
> +	struct iovec iov;
> +	struct msghdr msg;
> +
> +	iov.iov_base = (void*)(uintptr_t)buffer;
> +	iov.iov_len = len;
> +	msg.msg_name = NULL;
> +	msg.msg_namelen = 0;
> +	msg.msg_iov = &iov;
> +	msg.msg_iovlen = 1;
> +	msg.msg_control = NULL;
> +	msg.msg_controllen = 0;
> +
> +	r = recvmsg(handle->opfd, &msg, 0);
> +	if (r < 0)
> +		return -EIO;
> +	if (msg.msg_flags & MSG_TRUNC)
> +		return -ENOMEM;
> +
> +	return 0;
> +}
> +
> +/*
> + * Encrypt data
> + *
> + * @handle cipher handle - input
> + * @in plaintext data buffer - input
> + * @inlen length of in buffer - input
> + * @out ciphertext data buffer - output
> + * @outlen length of out buffer - input
> + * @iv buffer holding the IV (may be NULL if IV is not needed) - input
> + * @ivlen length of iv (should be zero if iv is NULL) - input
> + *
> + * return: 0 upon success
> + *	   < 0 in case of error
> + */
> +int kcapi_cipher_encrypt(struct kcapi_handle *handle,
> +			 const unsigned char *in, size_t inlen,
> +			 unsigned char *out, size_t outlen,
> +			 const unsigned char *iv, size_t ivlen)
> +{
> +	return _kcapi_cipher_crypt(handle, in, inlen, out, outlen,
> +				   iv, ivlen, ALG_OP_ENCRYPT);
> +}
> +
> +/*
> + * Decrypt data
> + *
> + * @handle cipher handle - input
> + * @in ciphertext data buffer - input
> + * @inlen length of in buffer - input
> + * @out plaintext data buffer - output
> + * @outlen length of out buffer - input
> + * @iv buffer holding the IV (may be NULL if IV is not needed) - input
> + * @ivlen length of iv (should be zero if iv is NULL) - input
> + *
> + * return: 0 upon success
> + *	   < 0 in case of error
> + */
> +int kcapi_cipher_decrypt(struct kcapi_handle *handle,
> +			 const unsigned char *in, size_t inlen,
> +			 unsigned char *out, size_t outlen,
> +			 const unsigned char *iv, size_t ivlen)
> +{
> +	return _kcapi_cipher_crypt(handle, in, inlen, out, outlen,
> +				   iv, ivlen, ALG_OP_DECRYPT);
> +}
> +
> +/************************************************************
> + * Application requiring cryptographic services
> + ************************************************************/
> +
> +static char hex_char_map_l[] = { '0', '1', '2', '3', '4', '5', '6', '7',
> +				 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
> +static char hex_char_map_u[] = { '0', '1', '2', '3', '4', '5', '6', '7',
> +				 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
> +static char hex_char(unsigned int bin, int u)
> +{
> +	if (bin < sizeof(hex_char_map_l))
> +		return (u) ? hex_char_map_u[bin] : hex_char_map_l[bin];
> +	return 'X';
> +}
> +
> +/*
> + * Convert binary string into hex representation
> + * @bin input buffer with binary data
> + * @binlen length of bin
> + * @hex output buffer to store hex data
> + * @hexlen length of already allocated hex buffer (should be at least
> + *	   twice binlen -- if not, only a fraction of binlen is converted)
> + * @u case of hex characters (0=>lower case, 1=>upper case)
> + */
> +static void bin2hex(const unsigned char *bin, size_t binlen,
> +		    char *hex, size_t hexlen, int u)
> +{
> +	size_t i = 0;
> +	size_t chars = (binlen > (hexlen / 2)) ? (hexlen / 2) : binlen;
> +
> +	for (i = 0; i < chars; i++) {
> +		hex[(i*2)] = hex_char((bin[i] >> 4), u);
> +		hex[((i*2)+1)] = hex_char((bin[i] & 0x0f), u);
> +	}
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +	struct kcapi_handle handle;
> +#define BUFLEN 32
> +	unsigned char inbuf[BUFLEN];
> +#define IVLEN 16
> +	unsigned char ivbuf[IVLEN];
> +	unsigned char outbuf[BUFLEN];
> +	unsigned char outbuf2[BUFLEN];
> +	char hexbuf[BUFLEN * 2 + 1];
> +
> +	(void)argc;
> +	(void)argv;
> +
> +	/*
> +	 * Calculate a message digest
> +	 */
> +	if (kcapi_cipher_init(&handle, "hash", "sha256")) {
> +		printf("Allocation of hash failed\n");
> +		return(1);
> +	}
> +	memcpy(inbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
> +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
> +		      "\x00\x01\x02\x03\x04\x05\x06\x07"
> +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", BUFLEN);
> +	if (kcapi_md_update(&handle, inbuf, BUFLEN)) {
> +		printf("Hash update of buffer failed\n");
> +		return(1);
> +	}
> +	if (kcapi_md_final(&handle, outbuf, BUFLEN)) {
> +		printf("Hash final failed\n");
> +		return(1);
> +	}
> +	kcapi_cipher_destory(&handle);
> +	memset(hexbuf, 0, BUFLEN * 2 + 1);
> +	bin2hex(outbuf, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
> +	printf("Calculated hash %s\n", hexbuf);
> +
> +	/*
> +	 * Calculate a keyed message digest
> +	 */
> +	if (kcapi_cipher_init(&handle, "hash", "hmac(sha256)")) {
> +		printf("Allocation of HMAC failed\n");
> +		return(1);
> +	}
> +	memcpy(inbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
> +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
> +		      "\x00\x01\x02\x03\x04\x05\x06\x07"
> +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", BUFLEN);
> +	if (kcapi_cipher_setkey(&handle, inbuf, BUFLEN)) {
> +		printf("HMAC setkey failed\n");
> +		return(1);
> +	}
> +	if (kcapi_md_update(&handle, inbuf, BUFLEN)) {
> +		printf("HMAC update of buffer failed\n");
> +		return(1);
> +	}
> +	if (kcapi_md_final(&handle, outbuf, BUFLEN)) {
> +		printf("HMAC final failed\n");
> +		return(1);
> +	}
> +	kcapi_cipher_destory(&handle);

Did you test building this?

> +	memset(hexbuf, 0, BUFLEN * 2 + 1);
> +	bin2hex(outbuf, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
> +	printf("Calculated hmac %s\n", hexbuf);
> +
> +	/*
> +	 * Encrypt data
> +	 */
> +	if (kcapi_cipher_init(&handle, "skcipher", "cbc(aes)")) {
> +		printf("Allocation of cipher failed\n");
> +		return(1);
> +	}
> +	memcpy(inbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
> +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
> +		      "\x00\x01\x02\x03\x04\x05\x06\x07"
> +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", BUFLEN);
> +	if (kcapi_cipher_setkey(&handle, inbuf, BUFLEN)) {
> +		printf("AES setkey failed\n");
> +		return(1);
> +	}
> +	memcpy(ivbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
> +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", IVLEN);
> +	if (kcapi_cipher_encrypt(&handle, inbuf, BUFLEN,
> +				 outbuf, BUFLEN, ivbuf, IVLEN)) {
> +		printf("Encryption buffer failed\n");
> +		return(1);
> +	}
> +	memset(hexbuf, 0, BUFLEN * 2 + 1);
> +	bin2hex(outbuf, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
> +	printf("Encrypted data %s\n", hexbuf);
> +
> +	/*
> +	 * Decrypt previously encrypted data
> +	 */
> +	if (kcapi_cipher_decrypt(&handle, outbuf, BUFLEN,
> +				 outbuf2, BUFLEN, ivbuf, IVLEN)) {
> +		printf("Decryption buffer failed\n");
> +		return(1);
> +	}
> +	kcapi_cipher_destory(&handle);
> +	memset(hexbuf, 0, BUFLEN * 2 + 1);
> +	bin2hex(outbuf2, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
> +	printf("Decrypted data %s\n", hexbuf);
> +	if (!memcmp(inbuf, outbuf2, BUFLEN))
> +		printf("Decrypted data match original plaintext as expected\n");
> +	else
> +		printf("FAILURE: Decrypted data does not match original plaintext\n");
> +
> +	return 0;
> +}
> +
> +License of code
> +===============
> +/*
> + * Copyright (C) 2014, Stephan Mueller <smueller@chronox.de>
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, and the entire permission notice in its entirety,
> + *    including the disclaimer of warranties.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. The name of the author may not be used to endorse or promote
> + *    products derived from this software without specific prior
> + *    written permission.
> + *
> + * ALTERNATIVELY, this product may be distributed under the terms of
> + * the GNU General Public License, in which case the provisions of the GPL2 are
> + * required INSTEAD OF the above restrictions.  (This clause is
> + * necessary due to a potential bad interaction between the GPL and
> + * the restrictions contained in a BSD-style copyright.)
> + *
> + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
> + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
> + * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
> + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
> + * DAMAGE.
> + */

Perhaps the userspace API example should be a separate file with this
text at the top?  Seems odd having it at the end.  Also, if you copied
it from cryptsetup, is the copyright info correct?

thx,

Jason.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] kernel crypto API interface specification
  2014-10-15 17:58 ` Jason Cooper
@ 2014-10-16  7:19   ` Stephan Mueller
  2014-10-16 13:25     ` Jason Cooper
  0 siblings, 1 reply; 14+ messages in thread
From: Stephan Mueller @ 2014-10-16  7:19 UTC (permalink / raw)
  To: Jason Cooper; +Cc: Herbert Xu, David S. Miller, linux-crypto, linux-kernel

Am Mittwoch, 15. Oktober 2014, 13:58:00 schrieb Jason Cooper:

Hi Jason,

> Stephan,
> 
> Wow.  This is very thorough.  Herbert and others will be making the
> final call on this, but if I may make a suggestion:

Thanks.
> 
> On Tue, Oct 14, 2014 at 09:46:50PM +0200, Stephan Mueller wrote:
> > The update adds a complete interface documentation of the kernel crypto
> > API. All cipher types supported by the kernel crypto API are documented.
> > 
> > In addition, kernel and user space example code is provided. The sample
> > code covers synchronous and asynchronous cipher operation, random
> > number generation and performing hashing as well as encryption and
> > decryption in user space.
> 
> This really needs to be split into at least two pieces.  The kernel and
> the userspace API.  I'd venture to say the userspace API portion of this
> document is almost ready.  But I'm not certain that the kernel
> interfaces are best described in a specification.

Good idea, I will split it.
> 
> APIs within the kernel are intentionally not nailed down and are very
> fluid.  Any attempt to spell them out in a document would mean either a)
> the document would be out of date quickly, or b) the maintainer now has
> to ask for changes to the docs every time a patch with a kernel API
> change comes in.  Neither scenario is good. :-(

Right, but on the other hand having no documentation at all is also bad. I 
know first hand how non-straight-forward it is to use the kernel crypto API as 
I programmed a test kernel module that invokes all cipher types available. 
Even with the examples in testmgr.c, I had a number of trial and errors. For 
crypto, this is not good.

Note, the mistakes you make are not easily seen, which is a problem if you 
want to protect data :-)

The key problem is that the kernel crypto API makes some assumptions on the 
memory layout and the concept of asymmetric requests. Furthermore, the AEAD 
definitions require different data types than offered by the API. That means 
the calling code must first massage the AEAD input data (see CCM IV vs nonce 
or the CCM/GCM tag handling).

Yet, I also see that a separate documentation may easily deviate from the real 
code (I know that first hand as I have to document parts of the kernel for 
some projects :-) ). Therefore I also suggested to take the API call 
documentation out and put it into the header files where the API calls are 
specified.
> 
> We certainly don't want to lose all of the effort you've put into
> grokking the API, so we need to find a maintainable place to add it.  I
> personally think adding comments above the respective function
> blocks would work well.

Right, as I also suggested in my follow-up email. Yet, I would like to hear an 
ok from the maintainers that I can touch these files.
> 
> The examples (kernel API) are another matter entirely.  Examples that
> aren't up-to-date and usable as a template aren't helpful to anyone.
> Some would even say detrimental.  And since example code isn't actually
> *used* in the real world, it would be an extra burden keeping it up to
> date.  I think these could best be used as a reference to compare all of
> the current users to.  Anything not up to par would generate a patch.
> The best examples should be the current users in the kernel.

Yes, that is what I also fear. Yet, using the asynchronous API may not be 
straight forward. Especially AEAD has some non-obvious requirements that may 
be documented best with an example. Yet, the example may be stripped down 
drastically to focus on the key aspects.
> 
> > Signed-off-by: Stephan Mueller <smueller@chronox.de>
> > ---
> > 
> >  Documentation/crypto/crypto-API-spec.txt | 2110
> >  ++++++++++++++++++++++++++++++ 1 file changed, 2110 insertions(+)
> >  create mode 100644 Documentation/crypto/crypto-API-spec.txt
> > 
> > diff --git a/Documentation/crypto/crypto-API-spec.txt
> > b/Documentation/crypto/crypto-API-spec.txt new file mode 100644
> > index 0000000..027fd4f
> > --- /dev/null
> > +++ b/Documentation/crypto/crypto-API-spec.txt
> > @@ -0,0 +1,2110 @@
> 
> [snip detailed explanation of current kernel API]
> 
> > +User space API
> > +==============
> > +
> > +The kernel crypto API is accessible from user space. Currently, the
> > following +ciphers are accessible:
> > +
> > +	* Message digest including keyed message digest
> > +
> > +	* Symmetric ciphers
> > +
> > +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.
> Perhaps a reference here to the final location of the kernel API
> explanations?

As I have now split out the user space API documentation from the rest. That 
document now refers back to the initial kernel-related API document.

That said, I added a precise reference to the cipher name documentation.
> 
> > +
> > +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.
> > +
> > +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_nmae = "sha1" /* this is the cipher name */
> > +};
> > +
> > +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 read() 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.
> 
> What happens if this is omitted?

Added:

"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 */
> > +};
> > +
> > +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 read() 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 the as many blocks are returned
> > that fit into that
> ...only as many blocks...

Fixed
> 
> > +output buffer size.
> > +
> > +User space API example
> > +----------------------
> > +
> > +Compile the following code with the gcc flags of "-Wextra -Wall
> > -pedantic". +
> > +/*
> > + * Code from cryptsetup version 1.6.4 used as a basis
> > + */
> 
> Could you specify the git commit and file from cryptsetup?  This way, if
> the this example becomes out of date, users could easily jump to the
> newest version of working code used in the real world.

I have not added the git commit as I think the version number is precise. Yet 
I added the files containing the implementation.

I would think that the user space API would not change as much as the kernel 
API could considering the standard approach by the kernel developers with user 
space APIs in general.
> 
> > +
> > +#include <stdio.h>
> > +
> > +#include <unistd.h>
> > +#include <sys/socket.h>
> > +#include <sys/types.h>
> > +#include <linux/if_alg.h>
> > +#include <stdint.h>
> > +#include <errno.h>
> > +#include <string.h>
> > +#include <stdlib.h>
> > +
> > +#ifndef AF_ALG
> > +#define AF_ALG 38
> > +#endif
> > +#ifndef SOL_ALG
> > +#define SOL_ALG 279
> > +#endif
> > +
> > +/************************************************************
> > + * Application interfaces
> > + ************************************************************/
> > +
> > +/* Cipher handle */
> > +struct kcapi_handle {
> > +	int tfmfd;
> > +	int opfd;
> > +};
> > +
> > +/************************************************************
> > + * Internal logic
> > + ************************************************************/
> > +
> > +/* The in/out should be aligned to page boundary */
> > +static int _kcapi_cipher_crypt(struct kcapi_handle *handle,
> > +			       const unsigned char *in, size_t inlen,
> > +			       unsigned char *out, size_t outlen,
> > +			       const unsigned char *iv, size_t ivlen,
> > +			       uint32_t enc)
> > +{
> > +	int r = 0;
> > +	ssize_t ret;
> > +	struct af_alg_iv *alg_iv;
> > +	struct cmsghdr *header;
> > +	uint32_t *type;
> > +	struct iovec iov;
> > +	int iv_msg_size = iv ? CMSG_SPACE(sizeof(*alg_iv) + ivlen) : 0;
> > +	char *buffer = NULL;
> > +	unsigned int bufferlen = CMSG_SPACE(sizeof(*type)) + iv_msg_size;
> > +	struct msghdr msg;
> > +
> > +	if (!in || !out || !inlen || !outlen)
> > +		return -EINVAL;
> > +
> > +	if ((!iv && ivlen) || (iv && !ivlen))
> > +		return -EINVAL;
> > +
> > +	buffer = calloc(1, bufferlen);
> > +	if (!buffer)
> > +		return -ENOMEM;
> > +
> > +	iov.iov_base = (void*)(uintptr_t)in;
> > +	iov.iov_len = inlen;
> > +	msg.msg_control = buffer;
> > +	msg.msg_controllen = bufferlen;
> > +	msg.msg_iov = &iov;
> > +	msg.msg_iovlen = 1;
> > +
> > +	/* encrypt/decrypt operation */
> > +	header = CMSG_FIRSTHDR(&msg);
> > +	header->cmsg_level = SOL_ALG;
> > +	header->cmsg_type = ALG_SET_OP;
> > +	header->cmsg_len = CMSG_LEN(sizeof(*type));
> > +	type = (void*)CMSG_DATA(header);
> > +	*type = enc;
> > +
> > +	/* set IV */
> > +	if (iv) {
> > +		header = CMSG_NXTHDR(&msg, header);
> > +		header->cmsg_level = SOL_ALG;
> > +		header->cmsg_type = ALG_SET_IV;
> > +		header->cmsg_len = iv_msg_size;
> > +		alg_iv = (void*)CMSG_DATA(header);
> > +		alg_iv->ivlen = ivlen;
> > +		memcpy(alg_iv->iv, iv, ivlen);
> > +	}
> > +
> > +	ret = sendmsg(handle->opfd, &msg, 0);
> > +	if (ret != (ssize_t)inlen) {
> > +		r = -EIO;
> > +		goto bad;
> > +	}
> > +
> > +	ret = read(handle->opfd, out, outlen);
> > +	if (ret != (ssize_t)outlen)
> > +		r = -EIO;
> > +bad:
> > +	memset(buffer, 0, bufferlen);
> 
> Not related to this patch, but you should take a look at:
> 
>   http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html
>  
> http://www.daemonology.net/blog/2014-09-06-zeroing-buffers-is-insufficient.
> html

Absolutely. Thanks for hinting to that. I added a memchr after the memset:

	memset(buffer, 0, bufferlen);
	_buffer = memchr(buffer, 1, bufferlen);
	if (_buffer)
		_buffer = '\0';
> > +	free(buffer);
> > +	return r;
> > +}
> > +
> > +
> > +/************************************************************
> > + * API to application
> > + ************************************************************/
> > +
> > +/*
> > + * Initialization of a cipher handle and establishing the connection to
> > + * the kernel
> > + *
> > + * @handle cipher handle filled during the call - output
> > + * @type cipher type, one of the following - input:
> > + *	 "hash" for message digests (including keyed message digests)
> > + *	 "skcipher" for symmetric ciphers
> > + * @ciphername kernel crypto API cipher name as specified in
> > + *	       /proc/crypto - input
> > + *
> > + * return: 0 upon success
> > + *	   < 0 in case of error
> > + *		ENOENT - algorithm not available
> > + *		ENOTSUP - AF_ALG family not available
> > + *		EINVAL - accept syscall failed
> > + */
> > +int kcapi_cipher_init(struct kcapi_handle *handle,
> > +		      const char *type, const char *ciphername)
> > +{
> > +	struct sockaddr_alg sa;
> > +
> > +	memset(&sa, 0, sizeof(sa));
> > +	sa.salg_family = AF_ALG;
> > +	snprintf((char *)sa.salg_type, sizeof(sa.salg_type),"%s", type);
> > +	snprintf((char *)sa.salg_name, sizeof(sa.salg_name),"%s", ciphername);
> > +
> > +	handle->tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
> > +	if (handle->tfmfd == -1)
> > +		return -ENOTSUP;
> > +
> > +	if (bind(handle->tfmfd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
> > +		close(handle->tfmfd);
> > +		handle->tfmfd = -1;
> > +		return -ENOENT;
> > +	}
> > +
> > +	handle->opfd = accept(handle->tfmfd, NULL, 0);
> > +	if (handle->opfd == -1) {
> > +		close(handle->tfmfd);
> > +		handle->tfmfd = -1;
> > +		return -EINVAL;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/*
> > + * Close the cipher handle and release resources
> > + *
> > + * @handle cipher handle to release - input
> > + *
> > + * return: 0 upon success
> > + */
> > +int kcapi_cipher_destory(struct kcapi_handle *handle)
> > +{
> > +	if (handle->tfmfd != -1)
> > +		close(handle->tfmfd);
> > +	if (handle->opfd != -1)
> > +		close(handle->opfd);
> > +	return 0;
> > +}
> > +
> > +
> > +/*
> > + * Set the key for the cipher handle
> > + *
> > + * This call is applicable for keyed message digests and symmetric
> > ciphers. + *
> > + * @handle cipher handle - input
> > + * @key key buffer - input
> > + * @keylen length of key buffer - input
> > + *
> > + * return: 0 upon success
> > + *	   < 0 in case of error
> > + */
> > +int kcapi_cipher_setkey(struct kcapi_handle *handle,
> > +			const unsigned char *key, size_t keylen)
> > +{
> > +	if (setsockopt(handle->tfmfd, SOL_ALG, ALG_SET_KEY,
> > +		       key, keylen) == -1)
> > +		return -EINVAL;
> > +
> > +	return 0;
> > +}
> > +
> > +/*
> > + * Message digest update function
> > + *
> > + * @handle cipher handle - input
> > + * @buffer holding the data to add to the message digest - input
> > + * @len buffer length - input
> > + *
> > + * return: 0 upon success
> > + *	   < 0 in case of error
> > + */
> > +int kcapi_md_update(struct kcapi_handle *handle,
> > +		    const unsigned char *buffer, size_t len)
> > +{
> > +	ssize_t r;
> > +
> > +	r = send(handle->opfd, buffer, len, MSG_MORE);
> > +	if (r < 0 || (size_t)r < len)
> > +		return -EIO;
> > +
> > +	return 0;
> > +}
> > +
> > +/*
> > + * Message digest finalization function
> > + *
> > + * @handle cipher handle - input
> > + * @buffer filled with the message digest - output
> > + * @len buffer length - input
> > + *
> > + * return: 0 upon success
> > + *	   < 0 in case of error
> > + *		EIO - data cannot be obtained
> > + *		ENOMEM - buffer is too small for the complete message digest,
> > + *			 the buffer is filled with the truncated message 
digest
> > + */
> > +
> > +int kcapi_md_final(struct kcapi_handle *handle,
> > +		   unsigned char *buffer, size_t len)
> > +{
> > +	ssize_t r;
> > +	struct iovec iov;
> > +	struct msghdr msg;
> > +
> > +	iov.iov_base = (void*)(uintptr_t)buffer;
> > +	iov.iov_len = len;
> > +	msg.msg_name = NULL;
> > +	msg.msg_namelen = 0;
> > +	msg.msg_iov = &iov;
> > +	msg.msg_iovlen = 1;
> > +	msg.msg_control = NULL;
> > +	msg.msg_controllen = 0;
> > +
> > +	r = recvmsg(handle->opfd, &msg, 0);
> > +	if (r < 0)
> > +		return -EIO;
> > +	if (msg.msg_flags & MSG_TRUNC)
> > +		return -ENOMEM;
> > +
> > +	return 0;
> > +}
> > +
> > +/*
> > + * Encrypt data
> > + *
> > + * @handle cipher handle - input
> > + * @in plaintext data buffer - input
> > + * @inlen length of in buffer - input
> > + * @out ciphertext data buffer - output
> > + * @outlen length of out buffer - input
> > + * @iv buffer holding the IV (may be NULL if IV is not needed) - input
> > + * @ivlen length of iv (should be zero if iv is NULL) - input
> > + *
> > + * return: 0 upon success
> > + *	   < 0 in case of error
> > + */
> > +int kcapi_cipher_encrypt(struct kcapi_handle *handle,
> > +			 const unsigned char *in, size_t inlen,
> > +			 unsigned char *out, size_t outlen,
> > +			 const unsigned char *iv, size_t ivlen)
> > +{
> > +	return _kcapi_cipher_crypt(handle, in, inlen, out, outlen,
> > +				   iv, ivlen, ALG_OP_ENCRYPT);
> > +}
> > +
> > +/*
> > + * Decrypt data
> > + *
> > + * @handle cipher handle - input
> > + * @in ciphertext data buffer - input
> > + * @inlen length of in buffer - input
> > + * @out plaintext data buffer - output
> > + * @outlen length of out buffer - input
> > + * @iv buffer holding the IV (may be NULL if IV is not needed) - input
> > + * @ivlen length of iv (should be zero if iv is NULL) - input
> > + *
> > + * return: 0 upon success
> > + *	   < 0 in case of error
> > + */
> > +int kcapi_cipher_decrypt(struct kcapi_handle *handle,
> > +			 const unsigned char *in, size_t inlen,
> > +			 unsigned char *out, size_t outlen,
> > +			 const unsigned char *iv, size_t ivlen)
> > +{
> > +	return _kcapi_cipher_crypt(handle, in, inlen, out, outlen,
> > +				   iv, ivlen, ALG_OP_DECRYPT);
> > +}
> > +
> > +/************************************************************
> > + * Application requiring cryptographic services
> > + ************************************************************/
> > +
> > +static char hex_char_map_l[] = { '0', '1', '2', '3', '4', '5', '6', '7',
> > +				 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
> > +static char hex_char_map_u[] = { '0', '1', '2', '3', '4', '5', '6', '7',
> > +				 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
> > +static char hex_char(unsigned int bin, int u)
> > +{
> > +	if (bin < sizeof(hex_char_map_l))
> > +		return (u) ? hex_char_map_u[bin] : hex_char_map_l[bin];
> > +	return 'X';
> > +}
> > +
> > +/*
> > + * Convert binary string into hex representation
> > + * @bin input buffer with binary data
> > + * @binlen length of bin
> > + * @hex output buffer to store hex data
> > + * @hexlen length of already allocated hex buffer (should be at least
> > + *	   twice binlen -- if not, only a fraction of binlen is converted)
> > + * @u case of hex characters (0=>lower case, 1=>upper case)
> > + */
> > +static void bin2hex(const unsigned char *bin, size_t binlen,
> > +		    char *hex, size_t hexlen, int u)
> > +{
> > +	size_t i = 0;
> > +	size_t chars = (binlen > (hexlen / 2)) ? (hexlen / 2) : binlen;
> > +
> > +	for (i = 0; i < chars; i++) {
> > +		hex[(i*2)] = hex_char((bin[i] >> 4), u);
> > +		hex[((i*2)+1)] = hex_char((bin[i] & 0x0f), u);
> > +	}
> > +}
> > +
> > +int main(int argc, char *argv[])
> > +{
> > +	struct kcapi_handle handle;
> > +#define BUFLEN 32
> > +	unsigned char inbuf[BUFLEN];
> > +#define IVLEN 16
> > +	unsigned char ivbuf[IVLEN];
> > +	unsigned char outbuf[BUFLEN];
> > +	unsigned char outbuf2[BUFLEN];
> > +	char hexbuf[BUFLEN * 2 + 1];
> > +
> > +	(void)argc;
> > +	(void)argv;
> > +
> > +	/*
> > +	 * Calculate a message digest
> > +	 */
> > +	if (kcapi_cipher_init(&handle, "hash", "sha256")) {
> > +		printf("Allocation of hash failed\n");
> > +		return(1);
> > +	}
> > +	memcpy(inbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
> > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
> > +		      "\x00\x01\x02\x03\x04\x05\x06\x07"
> > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", BUFLEN);
> > +	if (kcapi_md_update(&handle, inbuf, BUFLEN)) {
> > +		printf("Hash update of buffer failed\n");
> > +		return(1);
> > +	}
> > +	if (kcapi_md_final(&handle, outbuf, BUFLEN)) {
> > +		printf("Hash final failed\n");
> > +		return(1);
> > +	}
> > +	kcapi_cipher_destory(&handle);
> > +	memset(hexbuf, 0, BUFLEN * 2 + 1);
> > +	bin2hex(outbuf, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
> > +	printf("Calculated hash %s\n", hexbuf);
> > +
> > +	/*
> > +	 * Calculate a keyed message digest
> > +	 */
> > +	if (kcapi_cipher_init(&handle, "hash", "hmac(sha256)")) {
> > +		printf("Allocation of HMAC failed\n");
> > +		return(1);
> > +	}
> > +	memcpy(inbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
> > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
> > +		      "\x00\x01\x02\x03\x04\x05\x06\x07"
> > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", BUFLEN);
> > +	if (kcapi_cipher_setkey(&handle, inbuf, BUFLEN)) {
> > +		printf("HMAC setkey failed\n");
> > +		return(1);
> > +	}
> > +	if (kcapi_md_update(&handle, inbuf, BUFLEN)) {
> > +		printf("HMAC update of buffer failed\n");
> > +		return(1);
> > +	}
> > +	if (kcapi_md_final(&handle, outbuf, BUFLEN)) {
> > +		printf("HMAC final failed\n");
> > +		return(1);
> > +	}
> > +	kcapi_cipher_destory(&handle);
> 
> Did you test building this?

Yes, I did and it worked flawlessly. Just copy out the code and compile as 
stated in the comments. What are your concerns?

See the following code where I call kcapi_cipher_init again.
> 
> > +	memset(hexbuf, 0, BUFLEN * 2 + 1);
> > +	bin2hex(outbuf, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
> > +	printf("Calculated hmac %s\n", hexbuf);
> > +
> > +	/*
> > +	 * Encrypt data
> > +	 */
> > +	if (kcapi_cipher_init(&handle, "skcipher", "cbc(aes)")) {
> > +		printf("Allocation of cipher failed\n");
> > +		return(1);
> > +	}
> > +	memcpy(inbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
> > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
> > +		      "\x00\x01\x02\x03\x04\x05\x06\x07"
> > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", BUFLEN);
> > +	if (kcapi_cipher_setkey(&handle, inbuf, BUFLEN)) {
> > +		printf("AES setkey failed\n");
> > +		return(1);
> > +	}
> > +	memcpy(ivbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
> > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", IVLEN);
> > +	if (kcapi_cipher_encrypt(&handle, inbuf, BUFLEN,
> > +				 outbuf, BUFLEN, ivbuf, IVLEN)) {
> > +		printf("Encryption buffer failed\n");
> > +		return(1);
> > +	}
> > +	memset(hexbuf, 0, BUFLEN * 2 + 1);
> > +	bin2hex(outbuf, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
> > +	printf("Encrypted data %s\n", hexbuf);
> > +
> > +	/*
> > +	 * Decrypt previously encrypted data
> > +	 */
> > +	if (kcapi_cipher_decrypt(&handle, outbuf, BUFLEN,
> > +				 outbuf2, BUFLEN, ivbuf, IVLEN)) {
> > +		printf("Decryption buffer failed\n");
> > +		return(1);
> > +	}
> > +	kcapi_cipher_destory(&handle);
> > +	memset(hexbuf, 0, BUFLEN * 2 + 1);
> > +	bin2hex(outbuf2, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
> > +	printf("Decrypted data %s\n", hexbuf);
> > +	if (!memcmp(inbuf, outbuf2, BUFLEN))
> > +		printf("Decrypted data match original plaintext as 
expected\n");
> > +	else
> > +		printf("FAILURE: Decrypted data does not match original 
plaintext\n");
> > +
> > +	return 0;
> > +}
> > +
> > +License of code
> > +===============
> > +/*
> > + * Copyright (C) 2014, Stephan Mueller <smueller@chronox.de>
> > + *
> > + * Redistribution and use in source and binary forms, with or without
> > + * modification, are permitted provided that the following conditions
> > + * are met:
> > + * 1. Redistributions of source code must retain the above copyright
> > + *    notice, and the entire permission notice in its entirety,
> > + *    including the disclaimer of warranties.
> > + * 2. Redistributions in binary form must reproduce the above copyright
> > + *    notice, this list of conditions and the following disclaimer in the
> > + *    documentation and/or other materials provided with the
> > distribution.
> > + * 3. The name of the author may not be used to endorse or promote
> > + *    products derived from this software without specific prior
> > + *    written permission.
> > + *
> > + * ALTERNATIVELY, this product may be distributed under the terms of
> > + * the GNU General Public License, in which case the provisions of the
> > GPL2 are + * required INSTEAD OF the above restrictions.  (This clause is
> > + * necessary due to a potential bad interaction between the GPL and
> > + * the restrictions contained in a BSD-style copyright.)
> > + *
> > + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
> > + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
> > + * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
> > + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> > + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
> > + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> > + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> > + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> > + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
> > + * DAMAGE.
> > + */
> 
> Perhaps the userspace API example should be a separate file with this
> text at the top?  Seems odd having it at the end.  Also, if you copied
> it from cryptsetup, is the copyright info correct?

I did not copy it from cryptsetup. I only used it as a basis, especially with 
the data structure handling in _kcapi_cipher_crypt. But you are right, I 
changed the license for the user space by taking the cryptsetup license.

Thanks

-- 
Ciao
Stephan

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] kernel crypto API interface specification
  2014-10-14 19:46 [PATCH] kernel crypto API interface specification Stephan Mueller
  2014-10-14 20:00 ` Stephan Mueller
  2014-10-15 17:58 ` Jason Cooper
@ 2014-10-16 13:10 ` Herbert Xu
  2014-10-31  3:01   ` Marek Vasut
  2 siblings, 1 reply; 14+ messages in thread
From: Herbert Xu @ 2014-10-16 13:10 UTC (permalink / raw)
  To: Stephan Mueller; +Cc: David S. Miller, linux-crypto, linux-kernel, Marek Vasut

On Tue, Oct 14, 2014 at 09:46:50PM +0200, Stephan Mueller wrote:
> The update adds a complete interface documentation of the kernel crypto
> API. All cipher types supported by the kernel crypto API are documented.
> 
> In addition, kernel and user space example code is provided. The sample
> code covers synchronous and asynchronous cipher operation, random
> number generation and performing hashing as well as encryption and
> decryption in user space.
> 
> Signed-off-by: Stephan Mueller <smueller@chronox.de>

Thanks for the patch Stephan!

Marek Vasut <marex@denx.de> has also been working on a set of
documentation for the crypto API so he might have some comments
on this.

Cheers,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] kernel crypto API interface specification
  2014-10-16  7:19   ` Stephan Mueller
@ 2014-10-16 13:25     ` Jason Cooper
  2014-10-16 13:29       ` Jason Cooper
  2014-10-16 15:06       ` Jason Cooper
  0 siblings, 2 replies; 14+ messages in thread
From: Jason Cooper @ 2014-10-16 13:25 UTC (permalink / raw)
  To: Stephan Mueller; +Cc: Herbert Xu, David S. Miller, linux-crypto, linux-kernel

+ Grant, Geert,

Stephan has created some great example code for both the kernel crypto
API and the userspace crypto API.  As examples tend to bitrot, I was
wondering if the code could serve as test code.  Then it would have a
triple role: API regression testing, crypto test suite, and reference
implementation.

Original patch is here:

  https://lkml.kernel.org/r/7502136.9BkWHTZ0th@myon.chronox.de

On Thu, Oct 16, 2014 at 09:19:08AM +0200, Stephan Mueller wrote:
> Am Mittwoch, 15. Oktober 2014, 13:58:00 schrieb Jason Cooper:
> 
> Hi Jason,
> 
> > Stephan,
> > 
> > Wow.  This is very thorough.  Herbert and others will be making the
> > final call on this, but if I may make a suggestion:
> 
> Thanks.
> > 
> > On Tue, Oct 14, 2014 at 09:46:50PM +0200, Stephan Mueller wrote:
> > > The update adds a complete interface documentation of the kernel crypto
> > > API. All cipher types supported by the kernel crypto API are documented.
> > > 
> > > In addition, kernel and user space example code is provided. The sample
> > > code covers synchronous and asynchronous cipher operation, random
> > > number generation and performing hashing as well as encryption and
> > > decryption in user space.
> > 
> > This really needs to be split into at least two pieces.  The kernel and
> > the userspace API.  I'd venture to say the userspace API portion of this
> > document is almost ready.  But I'm not certain that the kernel
> > interfaces are best described in a specification.
> 
> Good idea, I will split it.
> > 
> > APIs within the kernel are intentionally not nailed down and are very
> > fluid.  Any attempt to spell them out in a document would mean either a)
> > the document would be out of date quickly, or b) the maintainer now has
> > to ask for changes to the docs every time a patch with a kernel API
> > change comes in.  Neither scenario is good. :-(
> 
> Right, but on the other hand having no documentation at all is also bad. I 
> know first hand how non-straight-forward it is to use the kernel crypto API as 
> I programmed a test kernel module that invokes all cipher types available. 
> Even with the examples in testmgr.c, I had a number of trial and errors. For 
> crypto, this is not good.
> 
> Note, the mistakes you make are not easily seen, which is a problem if you 
> want to protect data :-)
> 
> The key problem is that the kernel crypto API makes some assumptions on the 
> memory layout and the concept of asymmetric requests. Furthermore, the AEAD 
> definitions require different data types than offered by the API. That means 
> the calling code must first massage the AEAD input data (see CCM IV vs nonce 
> or the CCM/GCM tag handling).
> 
> Yet, I also see that a separate documentation may easily deviate from the real 
> code (I know that first hand as I have to document parts of the kernel for 
> some projects :-) ). Therefore I also suggested to take the API call 
> documentation out and put it into the header files where the API calls are 
> specified.
> > 
> > We certainly don't want to lose all of the effort you've put into
> > grokking the API, so we need to find a maintainable place to add it.  I
> > personally think adding comments above the respective function
> > blocks would work well.
> 
> Right, as I also suggested in my follow-up email. Yet, I would like to hear an 
> ok from the maintainers that I can touch these files.

That's like asking if you can ask a question.  Just do it.  :-)

> > The examples (kernel API) are another matter entirely.  Examples that
> > aren't up-to-date and usable as a template aren't helpful to anyone.
> > Some would even say detrimental.  And since example code isn't actually
> > *used* in the real world, it would be an extra burden keeping it up to
> > date.  I think these could best be used as a reference to compare all of
> > the current users to.  Anything not up to par would generate a patch.
> > The best examples should be the current users in the kernel.
> 
> Yes, that is what I also fear. Yet, using the asynchronous API may not be 
> straight forward. Especially AEAD has some non-obvious requirements that may 
> be documented best with an example. Yet, the example may be stripped down 
> drastically to focus on the key aspects.

Perhaps extending testmgr.c with your example code would be the best
answer.  There has been a push recently to have more comprehensive test
suites within the kernel.  If the test code is run often, it would make
a reasonable place for 'reference' implementations.

> > > Signed-off-by: Stephan Mueller <smueller@chronox.de>
> > > ---
> > > 
> > >  Documentation/crypto/crypto-API-spec.txt | 2110
> > >  ++++++++++++++++++++++++++++++ 1 file changed, 2110 insertions(+)
> > >  create mode 100644 Documentation/crypto/crypto-API-spec.txt
> > > 
> > > diff --git a/Documentation/crypto/crypto-API-spec.txt
> > > b/Documentation/crypto/crypto-API-spec.txt new file mode 100644
> > > index 0000000..027fd4f
> > > --- /dev/null
> > > +++ b/Documentation/crypto/crypto-API-spec.txt
> > > @@ -0,0 +1,2110 @@
> > 
> > [snip detailed explanation of current kernel API]
> > 
> > > +User space API
> > > +==============
> > > +
> > > +The kernel crypto API is accessible from user space. Currently, the
> > > following +ciphers are accessible:
> > > +
> > > +	* Message digest including keyed message digest
> > > +
> > > +	* Symmetric ciphers
> > > +
> > > +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.
> > Perhaps a reference here to the final location of the kernel API
> > explanations?
> 
> As I have now split out the user space API documentation from the rest. That 
> document now refers back to the initial kernel-related API document.
> 
> That said, I added a precise reference to the cipher name documentation.
> > 
> > > +
> > > +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.
> > > +
> > > +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_nmae = "sha1" /* this is the cipher name */
> > > +};
> > > +
> > > +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 read() 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.
> > 
> > What happens if this is omitted?
> 
> Added:
> 
> "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 */
> > > +};
> > > +
> > > +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 read() 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 the as many blocks are returned
> > > that fit into that
> > ...only as many blocks...
> 
> Fixed
> > 
> > > +output buffer size.
> > > +
> > > +User space API example
> > > +----------------------
> > > +
> > > +Compile the following code with the gcc flags of "-Wextra -Wall
> > > -pedantic". +
> > > +/*
> > > + * Code from cryptsetup version 1.6.4 used as a basis
> > > + */
> > 
> > Could you specify the git commit and file from cryptsetup?  This way, if
> > the this example becomes out of date, users could easily jump to the
> > newest version of working code used in the real world.
> 
> I have not added the git commit as I think the version number is precise. Yet 
> I added the files containing the implementation.
> 
> I would think that the user space API would not change as much as the kernel 
> API could considering the standard approach by the kernel developers with user 
> space APIs in general.

Agreed.

I got to thinking about this some more last night.  Why don't we split
out the below example code and make it a part of the kernel test
harness?  It could test for API regressions, and be a reference
implementation at the same time...

> > > +
> > > +#include <stdio.h>
> > > +
> > > +#include <unistd.h>
> > > +#include <sys/socket.h>
> > > +#include <sys/types.h>
> > > +#include <linux/if_alg.h>
> > > +#include <stdint.h>
> > > +#include <errno.h>
> > > +#include <string.h>
> > > +#include <stdlib.h>
> > > +
> > > +#ifndef AF_ALG
> > > +#define AF_ALG 38
> > > +#endif
> > > +#ifndef SOL_ALG
> > > +#define SOL_ALG 279
> > > +#endif
> > > +
> > > +/************************************************************
> > > + * Application interfaces
> > > + ************************************************************/
> > > +
> > > +/* Cipher handle */
> > > +struct kcapi_handle {
> > > +	int tfmfd;
> > > +	int opfd;
> > > +};
> > > +
> > > +/************************************************************
> > > + * Internal logic
> > > + ************************************************************/
> > > +
> > > +/* The in/out should be aligned to page boundary */
> > > +static int _kcapi_cipher_crypt(struct kcapi_handle *handle,
> > > +			       const unsigned char *in, size_t inlen,
> > > +			       unsigned char *out, size_t outlen,
> > > +			       const unsigned char *iv, size_t ivlen,
> > > +			       uint32_t enc)
> > > +{
> > > +	int r = 0;
> > > +	ssize_t ret;
> > > +	struct af_alg_iv *alg_iv;
> > > +	struct cmsghdr *header;
> > > +	uint32_t *type;
> > > +	struct iovec iov;
> > > +	int iv_msg_size = iv ? CMSG_SPACE(sizeof(*alg_iv) + ivlen) : 0;
> > > +	char *buffer = NULL;
> > > +	unsigned int bufferlen = CMSG_SPACE(sizeof(*type)) + iv_msg_size;
> > > +	struct msghdr msg;
> > > +
> > > +	if (!in || !out || !inlen || !outlen)
> > > +		return -EINVAL;
> > > +
> > > +	if ((!iv && ivlen) || (iv && !ivlen))
> > > +		return -EINVAL;
> > > +
> > > +	buffer = calloc(1, bufferlen);
> > > +	if (!buffer)
> > > +		return -ENOMEM;
> > > +
> > > +	iov.iov_base = (void*)(uintptr_t)in;
> > > +	iov.iov_len = inlen;
> > > +	msg.msg_control = buffer;
> > > +	msg.msg_controllen = bufferlen;
> > > +	msg.msg_iov = &iov;
> > > +	msg.msg_iovlen = 1;
> > > +
> > > +	/* encrypt/decrypt operation */
> > > +	header = CMSG_FIRSTHDR(&msg);
> > > +	header->cmsg_level = SOL_ALG;
> > > +	header->cmsg_type = ALG_SET_OP;
> > > +	header->cmsg_len = CMSG_LEN(sizeof(*type));
> > > +	type = (void*)CMSG_DATA(header);
> > > +	*type = enc;
> > > +
> > > +	/* set IV */
> > > +	if (iv) {
> > > +		header = CMSG_NXTHDR(&msg, header);
> > > +		header->cmsg_level = SOL_ALG;
> > > +		header->cmsg_type = ALG_SET_IV;
> > > +		header->cmsg_len = iv_msg_size;
> > > +		alg_iv = (void*)CMSG_DATA(header);
> > > +		alg_iv->ivlen = ivlen;
> > > +		memcpy(alg_iv->iv, iv, ivlen);
> > > +	}
> > > +
> > > +	ret = sendmsg(handle->opfd, &msg, 0);
> > > +	if (ret != (ssize_t)inlen) {
> > > +		r = -EIO;
> > > +		goto bad;
> > > +	}
> > > +
> > > +	ret = read(handle->opfd, out, outlen);
> > > +	if (ret != (ssize_t)outlen)
> > > +		r = -EIO;
> > > +bad:
> > > +	memset(buffer, 0, bufferlen);
> > 
> > Not related to this patch, but you should take a look at:
> > 
> >   http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html
> >  
> > http://www.daemonology.net/blog/2014-09-06-zeroing-buffers-is-insufficient.
> > html
> 
> Absolutely. Thanks for hinting to that. I added a memchr after the memset:
> 
> 	memset(buffer, 0, bufferlen);
> 	_buffer = memchr(buffer, 1, bufferlen);
> 	if (_buffer)
> 		_buffer = '\0';
> > > +	free(buffer);
> > > +	return r;
> > > +}
> > > +
> > > +
> > > +/************************************************************
> > > + * API to application
> > > + ************************************************************/
> > > +
> > > +/*
> > > + * Initialization of a cipher handle and establishing the connection to
> > > + * the kernel
> > > + *
> > > + * @handle cipher handle filled during the call - output
> > > + * @type cipher type, one of the following - input:
> > > + *	 "hash" for message digests (including keyed message digests)
> > > + *	 "skcipher" for symmetric ciphers
> > > + * @ciphername kernel crypto API cipher name as specified in
> > > + *	       /proc/crypto - input
> > > + *
> > > + * return: 0 upon success
> > > + *	   < 0 in case of error
> > > + *		ENOENT - algorithm not available
> > > + *		ENOTSUP - AF_ALG family not available
> > > + *		EINVAL - accept syscall failed
> > > + */
> > > +int kcapi_cipher_init(struct kcapi_handle *handle,
> > > +		      const char *type, const char *ciphername)
> > > +{
> > > +	struct sockaddr_alg sa;
> > > +
> > > +	memset(&sa, 0, sizeof(sa));
> > > +	sa.salg_family = AF_ALG;
> > > +	snprintf((char *)sa.salg_type, sizeof(sa.salg_type),"%s", type);
> > > +	snprintf((char *)sa.salg_name, sizeof(sa.salg_name),"%s", ciphername);
> > > +
> > > +	handle->tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
> > > +	if (handle->tfmfd == -1)
> > > +		return -ENOTSUP;
> > > +
> > > +	if (bind(handle->tfmfd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
> > > +		close(handle->tfmfd);
> > > +		handle->tfmfd = -1;
> > > +		return -ENOENT;
> > > +	}
> > > +
> > > +	handle->opfd = accept(handle->tfmfd, NULL, 0);
> > > +	if (handle->opfd == -1) {
> > > +		close(handle->tfmfd);
> > > +		handle->tfmfd = -1;
> > > +		return -EINVAL;
> > > +	}
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +/*
> > > + * Close the cipher handle and release resources
> > > + *
> > > + * @handle cipher handle to release - input
> > > + *
> > > + * return: 0 upon success
> > > + */
> > > +int kcapi_cipher_destory(struct kcapi_handle *handle)
> > > +{
> > > +	if (handle->tfmfd != -1)
> > > +		close(handle->tfmfd);
> > > +	if (handle->opfd != -1)
> > > +		close(handle->opfd);
> > > +	return 0;
> > > +}
> > > +
> > > +
> > > +/*
> > > + * Set the key for the cipher handle
> > > + *
> > > + * This call is applicable for keyed message digests and symmetric
> > > ciphers. + *
> > > + * @handle cipher handle - input
> > > + * @key key buffer - input
> > > + * @keylen length of key buffer - input
> > > + *
> > > + * return: 0 upon success
> > > + *	   < 0 in case of error
> > > + */
> > > +int kcapi_cipher_setkey(struct kcapi_handle *handle,
> > > +			const unsigned char *key, size_t keylen)
> > > +{
> > > +	if (setsockopt(handle->tfmfd, SOL_ALG, ALG_SET_KEY,
> > > +		       key, keylen) == -1)
> > > +		return -EINVAL;
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +/*
> > > + * Message digest update function
> > > + *
> > > + * @handle cipher handle - input
> > > + * @buffer holding the data to add to the message digest - input
> > > + * @len buffer length - input
> > > + *
> > > + * return: 0 upon success
> > > + *	   < 0 in case of error
> > > + */
> > > +int kcapi_md_update(struct kcapi_handle *handle,
> > > +		    const unsigned char *buffer, size_t len)
> > > +{
> > > +	ssize_t r;
> > > +
> > > +	r = send(handle->opfd, buffer, len, MSG_MORE);
> > > +	if (r < 0 || (size_t)r < len)
> > > +		return -EIO;
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +/*
> > > + * Message digest finalization function
> > > + *
> > > + * @handle cipher handle - input
> > > + * @buffer filled with the message digest - output
> > > + * @len buffer length - input
> > > + *
> > > + * return: 0 upon success
> > > + *	   < 0 in case of error
> > > + *		EIO - data cannot be obtained
> > > + *		ENOMEM - buffer is too small for the complete message digest,
> > > + *			 the buffer is filled with the truncated message 
> digest
> > > + */
> > > +
> > > +int kcapi_md_final(struct kcapi_handle *handle,
> > > +		   unsigned char *buffer, size_t len)
> > > +{
> > > +	ssize_t r;
> > > +	struct iovec iov;
> > > +	struct msghdr msg;
> > > +
> > > +	iov.iov_base = (void*)(uintptr_t)buffer;
> > > +	iov.iov_len = len;
> > > +	msg.msg_name = NULL;
> > > +	msg.msg_namelen = 0;
> > > +	msg.msg_iov = &iov;
> > > +	msg.msg_iovlen = 1;
> > > +	msg.msg_control = NULL;
> > > +	msg.msg_controllen = 0;
> > > +
> > > +	r = recvmsg(handle->opfd, &msg, 0);
> > > +	if (r < 0)
> > > +		return -EIO;
> > > +	if (msg.msg_flags & MSG_TRUNC)
> > > +		return -ENOMEM;
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +/*
> > > + * Encrypt data
> > > + *
> > > + * @handle cipher handle - input
> > > + * @in plaintext data buffer - input
> > > + * @inlen length of in buffer - input
> > > + * @out ciphertext data buffer - output
> > > + * @outlen length of out buffer - input
> > > + * @iv buffer holding the IV (may be NULL if IV is not needed) - input
> > > + * @ivlen length of iv (should be zero if iv is NULL) - input
> > > + *
> > > + * return: 0 upon success
> > > + *	   < 0 in case of error
> > > + */
> > > +int kcapi_cipher_encrypt(struct kcapi_handle *handle,
> > > +			 const unsigned char *in, size_t inlen,
> > > +			 unsigned char *out, size_t outlen,
> > > +			 const unsigned char *iv, size_t ivlen)
> > > +{
> > > +	return _kcapi_cipher_crypt(handle, in, inlen, out, outlen,
> > > +				   iv, ivlen, ALG_OP_ENCRYPT);
> > > +}
> > > +
> > > +/*
> > > + * Decrypt data
> > > + *
> > > + * @handle cipher handle - input
> > > + * @in ciphertext data buffer - input
> > > + * @inlen length of in buffer - input
> > > + * @out plaintext data buffer - output
> > > + * @outlen length of out buffer - input
> > > + * @iv buffer holding the IV (may be NULL if IV is not needed) - input
> > > + * @ivlen length of iv (should be zero if iv is NULL) - input
> > > + *
> > > + * return: 0 upon success
> > > + *	   < 0 in case of error
> > > + */
> > > +int kcapi_cipher_decrypt(struct kcapi_handle *handle,
> > > +			 const unsigned char *in, size_t inlen,
> > > +			 unsigned char *out, size_t outlen,
> > > +			 const unsigned char *iv, size_t ivlen)
> > > +{
> > > +	return _kcapi_cipher_crypt(handle, in, inlen, out, outlen,
> > > +				   iv, ivlen, ALG_OP_DECRYPT);
> > > +}
> > > +
> > > +/************************************************************
> > > + * Application requiring cryptographic services
> > > + ************************************************************/
> > > +
> > > +static char hex_char_map_l[] = { '0', '1', '2', '3', '4', '5', '6', '7',
> > > +				 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
> > > +static char hex_char_map_u[] = { '0', '1', '2', '3', '4', '5', '6', '7',
> > > +				 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
> > > +static char hex_char(unsigned int bin, int u)
> > > +{
> > > +	if (bin < sizeof(hex_char_map_l))
> > > +		return (u) ? hex_char_map_u[bin] : hex_char_map_l[bin];
> > > +	return 'X';
> > > +}
> > > +
> > > +/*
> > > + * Convert binary string into hex representation
> > > + * @bin input buffer with binary data
> > > + * @binlen length of bin
> > > + * @hex output buffer to store hex data
> > > + * @hexlen length of already allocated hex buffer (should be at least
> > > + *	   twice binlen -- if not, only a fraction of binlen is converted)
> > > + * @u case of hex characters (0=>lower case, 1=>upper case)
> > > + */
> > > +static void bin2hex(const unsigned char *bin, size_t binlen,
> > > +		    char *hex, size_t hexlen, int u)
> > > +{
> > > +	size_t i = 0;
> > > +	size_t chars = (binlen > (hexlen / 2)) ? (hexlen / 2) : binlen;
> > > +
> > > +	for (i = 0; i < chars; i++) {
> > > +		hex[(i*2)] = hex_char((bin[i] >> 4), u);
> > > +		hex[((i*2)+1)] = hex_char((bin[i] & 0x0f), u);
> > > +	}
> > > +}
> > > +
> > > +int main(int argc, char *argv[])
> > > +{
> > > +	struct kcapi_handle handle;
> > > +#define BUFLEN 32
> > > +	unsigned char inbuf[BUFLEN];
> > > +#define IVLEN 16
> > > +	unsigned char ivbuf[IVLEN];
> > > +	unsigned char outbuf[BUFLEN];
> > > +	unsigned char outbuf2[BUFLEN];
> > > +	char hexbuf[BUFLEN * 2 + 1];
> > > +
> > > +	(void)argc;
> > > +	(void)argv;
> > > +
> > > +	/*
> > > +	 * Calculate a message digest
> > > +	 */
> > > +	if (kcapi_cipher_init(&handle, "hash", "sha256")) {
> > > +		printf("Allocation of hash failed\n");
> > > +		return(1);
> > > +	}
> > > +	memcpy(inbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
> > > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
> > > +		      "\x00\x01\x02\x03\x04\x05\x06\x07"
> > > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", BUFLEN);
> > > +	if (kcapi_md_update(&handle, inbuf, BUFLEN)) {
> > > +		printf("Hash update of buffer failed\n");
> > > +		return(1);
> > > +	}
> > > +	if (kcapi_md_final(&handle, outbuf, BUFLEN)) {
> > > +		printf("Hash final failed\n");
> > > +		return(1);
> > > +	}
> > > +	kcapi_cipher_destory(&handle);
> > > +	memset(hexbuf, 0, BUFLEN * 2 + 1);
> > > +	bin2hex(outbuf, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
> > > +	printf("Calculated hash %s\n", hexbuf);
> > > +
> > > +	/*
> > > +	 * Calculate a keyed message digest
> > > +	 */
> > > +	if (kcapi_cipher_init(&handle, "hash", "hmac(sha256)")) {
> > > +		printf("Allocation of HMAC failed\n");
> > > +		return(1);
> > > +	}
> > > +	memcpy(inbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
> > > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
> > > +		      "\x00\x01\x02\x03\x04\x05\x06\x07"
> > > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", BUFLEN);
> > > +	if (kcapi_cipher_setkey(&handle, inbuf, BUFLEN)) {
> > > +		printf("HMAC setkey failed\n");
> > > +		return(1);
> > > +	}
> > > +	if (kcapi_md_update(&handle, inbuf, BUFLEN)) {
> > > +		printf("HMAC update of buffer failed\n");
> > > +		return(1);
> > > +	}
> > > +	if (kcapi_md_final(&handle, outbuf, BUFLEN)) {
> > > +		printf("HMAC final failed\n");
> > > +		return(1);
> > > +	}
> > > +	kcapi_cipher_destory(&handle);
> > 
> > Did you test building this?
> 
> Yes, I did and it worked flawlessly. Just copy out the code and compile as 
> stated in the comments. What are your concerns?

I just spotted 'destory' and casually mentioned it without grepping for
the other instances. :(  It looks like it's been mis-spelled
consistently. :-P 

> See the following code where I call kcapi_cipher_init again.
> > 
> > > +	memset(hexbuf, 0, BUFLEN * 2 + 1);
> > > +	bin2hex(outbuf, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
> > > +	printf("Calculated hmac %s\n", hexbuf);
> > > +
> > > +	/*
> > > +	 * Encrypt data
> > > +	 */
> > > +	if (kcapi_cipher_init(&handle, "skcipher", "cbc(aes)")) {
> > > +		printf("Allocation of cipher failed\n");
> > > +		return(1);
> > > +	}
> > > +	memcpy(inbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
> > > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
> > > +		      "\x00\x01\x02\x03\x04\x05\x06\x07"
> > > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", BUFLEN);
> > > +	if (kcapi_cipher_setkey(&handle, inbuf, BUFLEN)) {
> > > +		printf("AES setkey failed\n");
> > > +		return(1);
> > > +	}
> > > +	memcpy(ivbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
> > > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", IVLEN);
> > > +	if (kcapi_cipher_encrypt(&handle, inbuf, BUFLEN,
> > > +				 outbuf, BUFLEN, ivbuf, IVLEN)) {
> > > +		printf("Encryption buffer failed\n");
> > > +		return(1);
> > > +	}
> > > +	memset(hexbuf, 0, BUFLEN * 2 + 1);
> > > +	bin2hex(outbuf, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
> > > +	printf("Encrypted data %s\n", hexbuf);
> > > +
> > > +	/*
> > > +	 * Decrypt previously encrypted data
> > > +	 */
> > > +	if (kcapi_cipher_decrypt(&handle, outbuf, BUFLEN,
> > > +				 outbuf2, BUFLEN, ivbuf, IVLEN)) {
> > > +		printf("Decryption buffer failed\n");
> > > +		return(1);
> > > +	}
> > > +	kcapi_cipher_destory(&handle);
> > > +	memset(hexbuf, 0, BUFLEN * 2 + 1);
> > > +	bin2hex(outbuf2, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
> > > +	printf("Decrypted data %s\n", hexbuf);
> > > +	if (!memcmp(inbuf, outbuf2, BUFLEN))
> > > +		printf("Decrypted data match original plaintext as 
> expected\n");
> > > +	else
> > > +		printf("FAILURE: Decrypted data does not match original 
> plaintext\n");
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +License of code
> > > +===============
> > > +/*
> > > + * Copyright (C) 2014, Stephan Mueller <smueller@chronox.de>
> > > + *
> > > + * Redistribution and use in source and binary forms, with or without
> > > + * modification, are permitted provided that the following conditions
> > > + * are met:
> > > + * 1. Redistributions of source code must retain the above copyright
> > > + *    notice, and the entire permission notice in its entirety,
> > > + *    including the disclaimer of warranties.
> > > + * 2. Redistributions in binary form must reproduce the above copyright
> > > + *    notice, this list of conditions and the following disclaimer in the
> > > + *    documentation and/or other materials provided with the
> > > distribution.
> > > + * 3. The name of the author may not be used to endorse or promote
> > > + *    products derived from this software without specific prior
> > > + *    written permission.
> > > + *
> > > + * ALTERNATIVELY, this product may be distributed under the terms of
> > > + * the GNU General Public License, in which case the provisions of the
> > > GPL2 are + * required INSTEAD OF the above restrictions.  (This clause is
> > > + * necessary due to a potential bad interaction between the GPL and
> > > + * the restrictions contained in a BSD-style copyright.)
> > > + *
> > > + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
> > > + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> > > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
> > > + * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
> > > + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> > > + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
> > > + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> > > + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> > > + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> > > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> > > + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
> > > + * DAMAGE.
> > > + */
> > 
> > Perhaps the userspace API example should be a separate file with this
> > text at the top?  Seems odd having it at the end.  Also, if you copied
> > it from cryptsetup, is the copyright info correct?
> 
> I did not copy it from cryptsetup. I only used it as a basis, especially with 
> the data structure handling in _kcapi_cipher_crypt. But you are right, I 
> changed the license for the user space by taking the cryptsetup license.

Ok.  It looks like Geert and Grant took part in the kernel test
unconference, so I'm adding them to the Cc.  I hope they can give us
some pointers as to where we could hook in this code.  Then we can
simply refer to it from the userspace API document.

thx,

Jason.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] kernel crypto API interface specification
  2014-10-16 13:25     ` Jason Cooper
@ 2014-10-16 13:29       ` Jason Cooper
  2014-10-16 15:06       ` Jason Cooper
  1 sibling, 0 replies; 14+ messages in thread
From: Jason Cooper @ 2014-10-16 13:29 UTC (permalink / raw)
  To: Stephan Mueller, Grant Likely, Geert Uytterhoeven
  Cc: Herbert Xu, David S. Miller, linux-crypto, linux-kernel



On Thu, Oct 16, 2014 at 09:25:01AM -0400, Jason Cooper wrote:
> + Grant, Geert,

oops.  It helps if I actually *add* them.  Sorry for the noise.

> Stephan has created some great example code for both the kernel crypto
> API and the userspace crypto API.  As examples tend to bitrot, I was
> wondering if the code could serve as test code.  Then it would have a
> triple role: API regression testing, crypto test suite, and reference
> implementation.
> 
> Original patch is here:
> 
>   https://lkml.kernel.org/r/7502136.9BkWHTZ0th@myon.chronox.de
> 
> On Thu, Oct 16, 2014 at 09:19:08AM +0200, Stephan Mueller wrote:
> > Am Mittwoch, 15. Oktober 2014, 13:58:00 schrieb Jason Cooper:
> > 
> > Hi Jason,
> > 
> > > Stephan,
> > > 
> > > Wow.  This is very thorough.  Herbert and others will be making the
> > > final call on this, but if I may make a suggestion:
> > 
> > Thanks.
> > > 
> > > On Tue, Oct 14, 2014 at 09:46:50PM +0200, Stephan Mueller wrote:
> > > > The update adds a complete interface documentation of the kernel crypto
> > > > API. All cipher types supported by the kernel crypto API are documented.
> > > > 
> > > > In addition, kernel and user space example code is provided. The sample
> > > > code covers synchronous and asynchronous cipher operation, random
> > > > number generation and performing hashing as well as encryption and
> > > > decryption in user space.
> > > 
> > > This really needs to be split into at least two pieces.  The kernel and
> > > the userspace API.  I'd venture to say the userspace API portion of this
> > > document is almost ready.  But I'm not certain that the kernel
> > > interfaces are best described in a specification.
> > 
> > Good idea, I will split it.
> > > 
> > > APIs within the kernel are intentionally not nailed down and are very
> > > fluid.  Any attempt to spell them out in a document would mean either a)
> > > the document would be out of date quickly, or b) the maintainer now has
> > > to ask for changes to the docs every time a patch with a kernel API
> > > change comes in.  Neither scenario is good. :-(
> > 
> > Right, but on the other hand having no documentation at all is also bad. I 
> > know first hand how non-straight-forward it is to use the kernel crypto API as 
> > I programmed a test kernel module that invokes all cipher types available. 
> > Even with the examples in testmgr.c, I had a number of trial and errors. For 
> > crypto, this is not good.
> > 
> > Note, the mistakes you make are not easily seen, which is a problem if you 
> > want to protect data :-)
> > 
> > The key problem is that the kernel crypto API makes some assumptions on the 
> > memory layout and the concept of asymmetric requests. Furthermore, the AEAD 
> > definitions require different data types than offered by the API. That means 
> > the calling code must first massage the AEAD input data (see CCM IV vs nonce 
> > or the CCM/GCM tag handling).
> > 
> > Yet, I also see that a separate documentation may easily deviate from the real 
> > code (I know that first hand as I have to document parts of the kernel for 
> > some projects :-) ). Therefore I also suggested to take the API call 
> > documentation out and put it into the header files where the API calls are 
> > specified.
> > > 
> > > We certainly don't want to lose all of the effort you've put into
> > > grokking the API, so we need to find a maintainable place to add it.  I
> > > personally think adding comments above the respective function
> > > blocks would work well.
> > 
> > Right, as I also suggested in my follow-up email. Yet, I would like to hear an 
> > ok from the maintainers that I can touch these files.
> 
> That's like asking if you can ask a question.  Just do it.  :-)
> 
> > > The examples (kernel API) are another matter entirely.  Examples that
> > > aren't up-to-date and usable as a template aren't helpful to anyone.
> > > Some would even say detrimental.  And since example code isn't actually
> > > *used* in the real world, it would be an extra burden keeping it up to
> > > date.  I think these could best be used as a reference to compare all of
> > > the current users to.  Anything not up to par would generate a patch.
> > > The best examples should be the current users in the kernel.
> > 
> > Yes, that is what I also fear. Yet, using the asynchronous API may not be 
> > straight forward. Especially AEAD has some non-obvious requirements that may 
> > be documented best with an example. Yet, the example may be stripped down 
> > drastically to focus on the key aspects.
> 
> Perhaps extending testmgr.c with your example code would be the best
> answer.  There has been a push recently to have more comprehensive test
> suites within the kernel.  If the test code is run often, it would make
> a reasonable place for 'reference' implementations.
> 
> > > > Signed-off-by: Stephan Mueller <smueller@chronox.de>
> > > > ---
> > > > 
> > > >  Documentation/crypto/crypto-API-spec.txt | 2110
> > > >  ++++++++++++++++++++++++++++++ 1 file changed, 2110 insertions(+)
> > > >  create mode 100644 Documentation/crypto/crypto-API-spec.txt
> > > > 
> > > > diff --git a/Documentation/crypto/crypto-API-spec.txt
> > > > b/Documentation/crypto/crypto-API-spec.txt new file mode 100644
> > > > index 0000000..027fd4f
> > > > --- /dev/null
> > > > +++ b/Documentation/crypto/crypto-API-spec.txt
> > > > @@ -0,0 +1,2110 @@
> > > 
> > > [snip detailed explanation of current kernel API]
> > > 
> > > > +User space API
> > > > +==============
> > > > +
> > > > +The kernel crypto API is accessible from user space. Currently, the
> > > > following +ciphers are accessible:
> > > > +
> > > > +	* Message digest including keyed message digest
> > > > +
> > > > +	* Symmetric ciphers
> > > > +
> > > > +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.
> > > Perhaps a reference here to the final location of the kernel API
> > > explanations?
> > 
> > As I have now split out the user space API documentation from the rest. That 
> > document now refers back to the initial kernel-related API document.
> > 
> > That said, I added a precise reference to the cipher name documentation.
> > > 
> > > > +
> > > > +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.
> > > > +
> > > > +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_nmae = "sha1" /* this is the cipher name */
> > > > +};
> > > > +
> > > > +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 read() 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.
> > > 
> > > What happens if this is omitted?
> > 
> > Added:
> > 
> > "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 */
> > > > +};
> > > > +
> > > > +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 read() 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 the as many blocks are returned
> > > > that fit into that
> > > ...only as many blocks...
> > 
> > Fixed
> > > 
> > > > +output buffer size.
> > > > +
> > > > +User space API example
> > > > +----------------------
> > > > +
> > > > +Compile the following code with the gcc flags of "-Wextra -Wall
> > > > -pedantic". +
> > > > +/*
> > > > + * Code from cryptsetup version 1.6.4 used as a basis
> > > > + */
> > > 
> > > Could you specify the git commit and file from cryptsetup?  This way, if
> > > the this example becomes out of date, users could easily jump to the
> > > newest version of working code used in the real world.
> > 
> > I have not added the git commit as I think the version number is precise. Yet 
> > I added the files containing the implementation.
> > 
> > I would think that the user space API would not change as much as the kernel 
> > API could considering the standard approach by the kernel developers with user 
> > space APIs in general.
> 
> Agreed.
> 
> I got to thinking about this some more last night.  Why don't we split
> out the below example code and make it a part of the kernel test
> harness?  It could test for API regressions, and be a reference
> implementation at the same time...
> 
> > > > +
> > > > +#include <stdio.h>
> > > > +
> > > > +#include <unistd.h>
> > > > +#include <sys/socket.h>
> > > > +#include <sys/types.h>
> > > > +#include <linux/if_alg.h>
> > > > +#include <stdint.h>
> > > > +#include <errno.h>
> > > > +#include <string.h>
> > > > +#include <stdlib.h>
> > > > +
> > > > +#ifndef AF_ALG
> > > > +#define AF_ALG 38
> > > > +#endif
> > > > +#ifndef SOL_ALG
> > > > +#define SOL_ALG 279
> > > > +#endif
> > > > +
> > > > +/************************************************************
> > > > + * Application interfaces
> > > > + ************************************************************/
> > > > +
> > > > +/* Cipher handle */
> > > > +struct kcapi_handle {
> > > > +	int tfmfd;
> > > > +	int opfd;
> > > > +};
> > > > +
> > > > +/************************************************************
> > > > + * Internal logic
> > > > + ************************************************************/
> > > > +
> > > > +/* The in/out should be aligned to page boundary */
> > > > +static int _kcapi_cipher_crypt(struct kcapi_handle *handle,
> > > > +			       const unsigned char *in, size_t inlen,
> > > > +			       unsigned char *out, size_t outlen,
> > > > +			       const unsigned char *iv, size_t ivlen,
> > > > +			       uint32_t enc)
> > > > +{
> > > > +	int r = 0;
> > > > +	ssize_t ret;
> > > > +	struct af_alg_iv *alg_iv;
> > > > +	struct cmsghdr *header;
> > > > +	uint32_t *type;
> > > > +	struct iovec iov;
> > > > +	int iv_msg_size = iv ? CMSG_SPACE(sizeof(*alg_iv) + ivlen) : 0;
> > > > +	char *buffer = NULL;
> > > > +	unsigned int bufferlen = CMSG_SPACE(sizeof(*type)) + iv_msg_size;
> > > > +	struct msghdr msg;
> > > > +
> > > > +	if (!in || !out || !inlen || !outlen)
> > > > +		return -EINVAL;
> > > > +
> > > > +	if ((!iv && ivlen) || (iv && !ivlen))
> > > > +		return -EINVAL;
> > > > +
> > > > +	buffer = calloc(1, bufferlen);
> > > > +	if (!buffer)
> > > > +		return -ENOMEM;
> > > > +
> > > > +	iov.iov_base = (void*)(uintptr_t)in;
> > > > +	iov.iov_len = inlen;
> > > > +	msg.msg_control = buffer;
> > > > +	msg.msg_controllen = bufferlen;
> > > > +	msg.msg_iov = &iov;
> > > > +	msg.msg_iovlen = 1;
> > > > +
> > > > +	/* encrypt/decrypt operation */
> > > > +	header = CMSG_FIRSTHDR(&msg);
> > > > +	header->cmsg_level = SOL_ALG;
> > > > +	header->cmsg_type = ALG_SET_OP;
> > > > +	header->cmsg_len = CMSG_LEN(sizeof(*type));
> > > > +	type = (void*)CMSG_DATA(header);
> > > > +	*type = enc;
> > > > +
> > > > +	/* set IV */
> > > > +	if (iv) {
> > > > +		header = CMSG_NXTHDR(&msg, header);
> > > > +		header->cmsg_level = SOL_ALG;
> > > > +		header->cmsg_type = ALG_SET_IV;
> > > > +		header->cmsg_len = iv_msg_size;
> > > > +		alg_iv = (void*)CMSG_DATA(header);
> > > > +		alg_iv->ivlen = ivlen;
> > > > +		memcpy(alg_iv->iv, iv, ivlen);
> > > > +	}
> > > > +
> > > > +	ret = sendmsg(handle->opfd, &msg, 0);
> > > > +	if (ret != (ssize_t)inlen) {
> > > > +		r = -EIO;
> > > > +		goto bad;
> > > > +	}
> > > > +
> > > > +	ret = read(handle->opfd, out, outlen);
> > > > +	if (ret != (ssize_t)outlen)
> > > > +		r = -EIO;
> > > > +bad:
> > > > +	memset(buffer, 0, bufferlen);
> > > 
> > > Not related to this patch, but you should take a look at:
> > > 
> > >   http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html
> > >  
> > > http://www.daemonology.net/blog/2014-09-06-zeroing-buffers-is-insufficient.
> > > html
> > 
> > Absolutely. Thanks for hinting to that. I added a memchr after the memset:
> > 
> > 	memset(buffer, 0, bufferlen);
> > 	_buffer = memchr(buffer, 1, bufferlen);
> > 	if (_buffer)
> > 		_buffer = '\0';
> > > > +	free(buffer);
> > > > +	return r;
> > > > +}
> > > > +
> > > > +
> > > > +/************************************************************
> > > > + * API to application
> > > > + ************************************************************/
> > > > +
> > > > +/*
> > > > + * Initialization of a cipher handle and establishing the connection to
> > > > + * the kernel
> > > > + *
> > > > + * @handle cipher handle filled during the call - output
> > > > + * @type cipher type, one of the following - input:
> > > > + *	 "hash" for message digests (including keyed message digests)
> > > > + *	 "skcipher" for symmetric ciphers
> > > > + * @ciphername kernel crypto API cipher name as specified in
> > > > + *	       /proc/crypto - input
> > > > + *
> > > > + * return: 0 upon success
> > > > + *	   < 0 in case of error
> > > > + *		ENOENT - algorithm not available
> > > > + *		ENOTSUP - AF_ALG family not available
> > > > + *		EINVAL - accept syscall failed
> > > > + */
> > > > +int kcapi_cipher_init(struct kcapi_handle *handle,
> > > > +		      const char *type, const char *ciphername)
> > > > +{
> > > > +	struct sockaddr_alg sa;
> > > > +
> > > > +	memset(&sa, 0, sizeof(sa));
> > > > +	sa.salg_family = AF_ALG;
> > > > +	snprintf((char *)sa.salg_type, sizeof(sa.salg_type),"%s", type);
> > > > +	snprintf((char *)sa.salg_name, sizeof(sa.salg_name),"%s", ciphername);
> > > > +
> > > > +	handle->tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
> > > > +	if (handle->tfmfd == -1)
> > > > +		return -ENOTSUP;
> > > > +
> > > > +	if (bind(handle->tfmfd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
> > > > +		close(handle->tfmfd);
> > > > +		handle->tfmfd = -1;
> > > > +		return -ENOENT;
> > > > +	}
> > > > +
> > > > +	handle->opfd = accept(handle->tfmfd, NULL, 0);
> > > > +	if (handle->opfd == -1) {
> > > > +		close(handle->tfmfd);
> > > > +		handle->tfmfd = -1;
> > > > +		return -EINVAL;
> > > > +	}
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +/*
> > > > + * Close the cipher handle and release resources
> > > > + *
> > > > + * @handle cipher handle to release - input
> > > > + *
> > > > + * return: 0 upon success
> > > > + */
> > > > +int kcapi_cipher_destory(struct kcapi_handle *handle)
> > > > +{
> > > > +	if (handle->tfmfd != -1)
> > > > +		close(handle->tfmfd);
> > > > +	if (handle->opfd != -1)
> > > > +		close(handle->opfd);
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +
> > > > +/*
> > > > + * Set the key for the cipher handle
> > > > + *
> > > > + * This call is applicable for keyed message digests and symmetric
> > > > ciphers. + *
> > > > + * @handle cipher handle - input
> > > > + * @key key buffer - input
> > > > + * @keylen length of key buffer - input
> > > > + *
> > > > + * return: 0 upon success
> > > > + *	   < 0 in case of error
> > > > + */
> > > > +int kcapi_cipher_setkey(struct kcapi_handle *handle,
> > > > +			const unsigned char *key, size_t keylen)
> > > > +{
> > > > +	if (setsockopt(handle->tfmfd, SOL_ALG, ALG_SET_KEY,
> > > > +		       key, keylen) == -1)
> > > > +		return -EINVAL;
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +/*
> > > > + * Message digest update function
> > > > + *
> > > > + * @handle cipher handle - input
> > > > + * @buffer holding the data to add to the message digest - input
> > > > + * @len buffer length - input
> > > > + *
> > > > + * return: 0 upon success
> > > > + *	   < 0 in case of error
> > > > + */
> > > > +int kcapi_md_update(struct kcapi_handle *handle,
> > > > +		    const unsigned char *buffer, size_t len)
> > > > +{
> > > > +	ssize_t r;
> > > > +
> > > > +	r = send(handle->opfd, buffer, len, MSG_MORE);
> > > > +	if (r < 0 || (size_t)r < len)
> > > > +		return -EIO;
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +/*
> > > > + * Message digest finalization function
> > > > + *
> > > > + * @handle cipher handle - input
> > > > + * @buffer filled with the message digest - output
> > > > + * @len buffer length - input
> > > > + *
> > > > + * return: 0 upon success
> > > > + *	   < 0 in case of error
> > > > + *		EIO - data cannot be obtained
> > > > + *		ENOMEM - buffer is too small for the complete message digest,
> > > > + *			 the buffer is filled with the truncated message 
> > digest
> > > > + */
> > > > +
> > > > +int kcapi_md_final(struct kcapi_handle *handle,
> > > > +		   unsigned char *buffer, size_t len)
> > > > +{
> > > > +	ssize_t r;
> > > > +	struct iovec iov;
> > > > +	struct msghdr msg;
> > > > +
> > > > +	iov.iov_base = (void*)(uintptr_t)buffer;
> > > > +	iov.iov_len = len;
> > > > +	msg.msg_name = NULL;
> > > > +	msg.msg_namelen = 0;
> > > > +	msg.msg_iov = &iov;
> > > > +	msg.msg_iovlen = 1;
> > > > +	msg.msg_control = NULL;
> > > > +	msg.msg_controllen = 0;
> > > > +
> > > > +	r = recvmsg(handle->opfd, &msg, 0);
> > > > +	if (r < 0)
> > > > +		return -EIO;
> > > > +	if (msg.msg_flags & MSG_TRUNC)
> > > > +		return -ENOMEM;
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +/*
> > > > + * Encrypt data
> > > > + *
> > > > + * @handle cipher handle - input
> > > > + * @in plaintext data buffer - input
> > > > + * @inlen length of in buffer - input
> > > > + * @out ciphertext data buffer - output
> > > > + * @outlen length of out buffer - input
> > > > + * @iv buffer holding the IV (may be NULL if IV is not needed) - input
> > > > + * @ivlen length of iv (should be zero if iv is NULL) - input
> > > > + *
> > > > + * return: 0 upon success
> > > > + *	   < 0 in case of error
> > > > + */
> > > > +int kcapi_cipher_encrypt(struct kcapi_handle *handle,
> > > > +			 const unsigned char *in, size_t inlen,
> > > > +			 unsigned char *out, size_t outlen,
> > > > +			 const unsigned char *iv, size_t ivlen)
> > > > +{
> > > > +	return _kcapi_cipher_crypt(handle, in, inlen, out, outlen,
> > > > +				   iv, ivlen, ALG_OP_ENCRYPT);
> > > > +}
> > > > +
> > > > +/*
> > > > + * Decrypt data
> > > > + *
> > > > + * @handle cipher handle - input
> > > > + * @in ciphertext data buffer - input
> > > > + * @inlen length of in buffer - input
> > > > + * @out plaintext data buffer - output
> > > > + * @outlen length of out buffer - input
> > > > + * @iv buffer holding the IV (may be NULL if IV is not needed) - input
> > > > + * @ivlen length of iv (should be zero if iv is NULL) - input
> > > > + *
> > > > + * return: 0 upon success
> > > > + *	   < 0 in case of error
> > > > + */
> > > > +int kcapi_cipher_decrypt(struct kcapi_handle *handle,
> > > > +			 const unsigned char *in, size_t inlen,
> > > > +			 unsigned char *out, size_t outlen,
> > > > +			 const unsigned char *iv, size_t ivlen)
> > > > +{
> > > > +	return _kcapi_cipher_crypt(handle, in, inlen, out, outlen,
> > > > +				   iv, ivlen, ALG_OP_DECRYPT);
> > > > +}
> > > > +
> > > > +/************************************************************
> > > > + * Application requiring cryptographic services
> > > > + ************************************************************/
> > > > +
> > > > +static char hex_char_map_l[] = { '0', '1', '2', '3', '4', '5', '6', '7',
> > > > +				 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
> > > > +static char hex_char_map_u[] = { '0', '1', '2', '3', '4', '5', '6', '7',
> > > > +				 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
> > > > +static char hex_char(unsigned int bin, int u)
> > > > +{
> > > > +	if (bin < sizeof(hex_char_map_l))
> > > > +		return (u) ? hex_char_map_u[bin] : hex_char_map_l[bin];
> > > > +	return 'X';
> > > > +}
> > > > +
> > > > +/*
> > > > + * Convert binary string into hex representation
> > > > + * @bin input buffer with binary data
> > > > + * @binlen length of bin
> > > > + * @hex output buffer to store hex data
> > > > + * @hexlen length of already allocated hex buffer (should be at least
> > > > + *	   twice binlen -- if not, only a fraction of binlen is converted)
> > > > + * @u case of hex characters (0=>lower case, 1=>upper case)
> > > > + */
> > > > +static void bin2hex(const unsigned char *bin, size_t binlen,
> > > > +		    char *hex, size_t hexlen, int u)
> > > > +{
> > > > +	size_t i = 0;
> > > > +	size_t chars = (binlen > (hexlen / 2)) ? (hexlen / 2) : binlen;
> > > > +
> > > > +	for (i = 0; i < chars; i++) {
> > > > +		hex[(i*2)] = hex_char((bin[i] >> 4), u);
> > > > +		hex[((i*2)+1)] = hex_char((bin[i] & 0x0f), u);
> > > > +	}
> > > > +}
> > > > +
> > > > +int main(int argc, char *argv[])
> > > > +{
> > > > +	struct kcapi_handle handle;
> > > > +#define BUFLEN 32
> > > > +	unsigned char inbuf[BUFLEN];
> > > > +#define IVLEN 16
> > > > +	unsigned char ivbuf[IVLEN];
> > > > +	unsigned char outbuf[BUFLEN];
> > > > +	unsigned char outbuf2[BUFLEN];
> > > > +	char hexbuf[BUFLEN * 2 + 1];
> > > > +
> > > > +	(void)argc;
> > > > +	(void)argv;
> > > > +
> > > > +	/*
> > > > +	 * Calculate a message digest
> > > > +	 */
> > > > +	if (kcapi_cipher_init(&handle, "hash", "sha256")) {
> > > > +		printf("Allocation of hash failed\n");
> > > > +		return(1);
> > > > +	}
> > > > +	memcpy(inbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
> > > > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
> > > > +		      "\x00\x01\x02\x03\x04\x05\x06\x07"
> > > > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", BUFLEN);
> > > > +	if (kcapi_md_update(&handle, inbuf, BUFLEN)) {
> > > > +		printf("Hash update of buffer failed\n");
> > > > +		return(1);
> > > > +	}
> > > > +	if (kcapi_md_final(&handle, outbuf, BUFLEN)) {
> > > > +		printf("Hash final failed\n");
> > > > +		return(1);
> > > > +	}
> > > > +	kcapi_cipher_destory(&handle);
> > > > +	memset(hexbuf, 0, BUFLEN * 2 + 1);
> > > > +	bin2hex(outbuf, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
> > > > +	printf("Calculated hash %s\n", hexbuf);
> > > > +
> > > > +	/*
> > > > +	 * Calculate a keyed message digest
> > > > +	 */
> > > > +	if (kcapi_cipher_init(&handle, "hash", "hmac(sha256)")) {
> > > > +		printf("Allocation of HMAC failed\n");
> > > > +		return(1);
> > > > +	}
> > > > +	memcpy(inbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
> > > > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
> > > > +		      "\x00\x01\x02\x03\x04\x05\x06\x07"
> > > > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", BUFLEN);
> > > > +	if (kcapi_cipher_setkey(&handle, inbuf, BUFLEN)) {
> > > > +		printf("HMAC setkey failed\n");
> > > > +		return(1);
> > > > +	}
> > > > +	if (kcapi_md_update(&handle, inbuf, BUFLEN)) {
> > > > +		printf("HMAC update of buffer failed\n");
> > > > +		return(1);
> > > > +	}
> > > > +	if (kcapi_md_final(&handle, outbuf, BUFLEN)) {
> > > > +		printf("HMAC final failed\n");
> > > > +		return(1);
> > > > +	}
> > > > +	kcapi_cipher_destory(&handle);
> > > 
> > > Did you test building this?
> > 
> > Yes, I did and it worked flawlessly. Just copy out the code and compile as 
> > stated in the comments. What are your concerns?
> 
> I just spotted 'destory' and casually mentioned it without grepping for
> the other instances. :(  It looks like it's been mis-spelled
> consistently. :-P 
> 
> > See the following code where I call kcapi_cipher_init again.
> > > 
> > > > +	memset(hexbuf, 0, BUFLEN * 2 + 1);
> > > > +	bin2hex(outbuf, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
> > > > +	printf("Calculated hmac %s\n", hexbuf);
> > > > +
> > > > +	/*
> > > > +	 * Encrypt data
> > > > +	 */
> > > > +	if (kcapi_cipher_init(&handle, "skcipher", "cbc(aes)")) {
> > > > +		printf("Allocation of cipher failed\n");
> > > > +		return(1);
> > > > +	}
> > > > +	memcpy(inbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
> > > > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
> > > > +		      "\x00\x01\x02\x03\x04\x05\x06\x07"
> > > > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", BUFLEN);
> > > > +	if (kcapi_cipher_setkey(&handle, inbuf, BUFLEN)) {
> > > > +		printf("AES setkey failed\n");
> > > > +		return(1);
> > > > +	}
> > > > +	memcpy(ivbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
> > > > +		      "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", IVLEN);
> > > > +	if (kcapi_cipher_encrypt(&handle, inbuf, BUFLEN,
> > > > +				 outbuf, BUFLEN, ivbuf, IVLEN)) {
> > > > +		printf("Encryption buffer failed\n");
> > > > +		return(1);
> > > > +	}
> > > > +	memset(hexbuf, 0, BUFLEN * 2 + 1);
> > > > +	bin2hex(outbuf, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
> > > > +	printf("Encrypted data %s\n", hexbuf);
> > > > +
> > > > +	/*
> > > > +	 * Decrypt previously encrypted data
> > > > +	 */
> > > > +	if (kcapi_cipher_decrypt(&handle, outbuf, BUFLEN,
> > > > +				 outbuf2, BUFLEN, ivbuf, IVLEN)) {
> > > > +		printf("Decryption buffer failed\n");
> > > > +		return(1);
> > > > +	}
> > > > +	kcapi_cipher_destory(&handle);
> > > > +	memset(hexbuf, 0, BUFLEN * 2 + 1);
> > > > +	bin2hex(outbuf2, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
> > > > +	printf("Decrypted data %s\n", hexbuf);
> > > > +	if (!memcmp(inbuf, outbuf2, BUFLEN))
> > > > +		printf("Decrypted data match original plaintext as 
> > expected\n");
> > > > +	else
> > > > +		printf("FAILURE: Decrypted data does not match original 
> > plaintext\n");
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +License of code
> > > > +===============
> > > > +/*
> > > > + * Copyright (C) 2014, Stephan Mueller <smueller@chronox.de>
> > > > + *
> > > > + * Redistribution and use in source and binary forms, with or without
> > > > + * modification, are permitted provided that the following conditions
> > > > + * are met:
> > > > + * 1. Redistributions of source code must retain the above copyright
> > > > + *    notice, and the entire permission notice in its entirety,
> > > > + *    including the disclaimer of warranties.
> > > > + * 2. Redistributions in binary form must reproduce the above copyright
> > > > + *    notice, this list of conditions and the following disclaimer in the
> > > > + *    documentation and/or other materials provided with the
> > > > distribution.
> > > > + * 3. The name of the author may not be used to endorse or promote
> > > > + *    products derived from this software without specific prior
> > > > + *    written permission.
> > > > + *
> > > > + * ALTERNATIVELY, this product may be distributed under the terms of
> > > > + * the GNU General Public License, in which case the provisions of the
> > > > GPL2 are + * required INSTEAD OF the above restrictions.  (This clause is
> > > > + * necessary due to a potential bad interaction between the GPL and
> > > > + * the restrictions contained in a BSD-style copyright.)
> > > > + *
> > > > + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
> > > > + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> > > > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
> > > > + * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
> > > > + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> > > > + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
> > > > + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> > > > + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> > > > + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> > > > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> > > > + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
> > > > + * DAMAGE.
> > > > + */
> > > 
> > > Perhaps the userspace API example should be a separate file with this
> > > text at the top?  Seems odd having it at the end.  Also, if you copied
> > > it from cryptsetup, is the copyright info correct?
> > 
> > I did not copy it from cryptsetup. I only used it as a basis, especially with 
> > the data structure handling in _kcapi_cipher_crypt. But you are right, I 
> > changed the license for the user space by taking the cryptsetup license.
> 
> Ok.  It looks like Geert and Grant took part in the kernel test
> unconference, so I'm adding them to the Cc.  I hope they can give us
> some pointers as to where we could hook in this code.  Then we can
> simply refer to it from the userspace API document.
> 
> thx,
> 
> Jason.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] kernel crypto API interface specification
  2014-10-16 13:25     ` Jason Cooper
  2014-10-16 13:29       ` Jason Cooper
@ 2014-10-16 15:06       ` Jason Cooper
  2014-10-16 16:50         ` Stephan Mueller
  1 sibling, 1 reply; 14+ messages in thread
From: Jason Cooper @ 2014-10-16 15:06 UTC (permalink / raw)
  To: Stephan Mueller, Grant Likely, Geert Uytterhoeven
  Cc: Herbert Xu, David S. Miller, linux-crypto, linux-kernel

On Thu, Oct 16, 2014 at 09:25:01AM -0400, Jason Cooper wrote:
> + Grant, Geert,
> 
> Stephan has created some great example code for both the kernel crypto
> API and the userspace crypto API.  As examples tend to bitrot, I was
> wondering if the code could serve as test code.  Then it would have a
> triple role: API regression testing, crypto test suite, and reference
> implementation.
> 
> Original patch is here:
> 
>   https://lkml.kernel.org/r/7502136.9BkWHTZ0th@myon.chronox.de
> 
> On Thu, Oct 16, 2014 at 09:19:08AM +0200, Stephan Mueller wrote:
> > Am Mittwoch, 15. Oktober 2014, 13:58:00 schrieb Jason Cooper:
> > > On Tue, Oct 14, 2014 at 09:46:50PM +0200, Stephan Mueller wrote:
...
> > > Perhaps the userspace API example should be a separate file with this
> > > text at the top?  Seems odd having it at the end.  Also, if you copied
> > > it from cryptsetup, is the copyright info correct?
> > 
> > I did not copy it from cryptsetup. I only used it as a basis, especially with 
> > the data structure handling in _kcapi_cipher_crypt. But you are right, I 
> > changed the license for the user space by taking the cryptsetup license.
> 
> Ok.  It looks like Geert and Grant took part in the kernel test
> unconference, so I'm adding them to the Cc.  I hope they can give us
> some pointers as to where we could hook in this code.  Then we can
> simply refer to it from the userspace API document.

tools/testing/selftests/crypto would be a good location for the example
code in the next version of this patch.  Make sure to take a look at
tools/testing/selftests/README.txt.

thx,

Jason.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] kernel crypto API interface specification
  2014-10-16 15:06       ` Jason Cooper
@ 2014-10-16 16:50         ` Stephan Mueller
  2014-10-16 17:42           ` Jason Cooper
  0 siblings, 1 reply; 14+ messages in thread
From: Stephan Mueller @ 2014-10-16 16:50 UTC (permalink / raw)
  To: Jason Cooper
  Cc: Grant Likely, Geert Uytterhoeven, Herbert Xu, David S. Miller,
	linux-crypto, linux-kernel

Am Donnerstag, 16. Oktober 2014, 11:06:05 schrieb Jason Cooper:

Hi Jason,

> On Thu, Oct 16, 2014 at 09:25:01AM -0400, Jason Cooper wrote:
> > + Grant, Geert,
> > 
> > Stephan has created some great example code for both the kernel crypto
> > API and the userspace crypto API.  As examples tend to bitrot, I was
> > wondering if the code could serve as test code.  Then it would have a
> > triple role: API regression testing, crypto test suite, and reference
> > implementation.
> > 
> > Original patch is here:
> >   https://lkml.kernel.org/r/7502136.9BkWHTZ0th@myon.chronox.de
> > 
> > On Thu, Oct 16, 2014 at 09:19:08AM +0200, Stephan Mueller wrote:
> > > Am Mittwoch, 15. Oktober 2014, 13:58:00 schrieb Jason Cooper:
> > > > On Tue, Oct 14, 2014 at 09:46:50PM +0200, Stephan Mueller wrote:
> ...
> 
> > > > Perhaps the userspace API example should be a separate file with this
> > > > text at the top?  Seems odd having it at the end.  Also, if you copied
> > > > it from cryptsetup, is the copyright info correct?
> > > 
> > > I did not copy it from cryptsetup. I only used it as a basis, especially
> > > with the data structure handling in _kcapi_cipher_crypt. But you are
> > > right, I changed the license for the user space by taking the
> > > cryptsetup license.> 
> > Ok.  It looks like Geert and Grant took part in the kernel test
> > unconference, so I'm adding them to the Cc.  I hope they can give us
> > some pointers as to where we could hook in this code.  Then we can
> > simply refer to it from the userspace API document.
> 
> tools/testing/selftests/crypto would be a good location for the example
> code in the next version of this patch.  Make sure to take a look at
> tools/testing/selftests/README.txt.

Well, I have written a FIPS 140-2 CAVS test harness covering all ciphers NIST 
is interested. Maybe this can go there?

> 
> thx,
> 
> Jason.


-- 
Ciao
Stephan

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] kernel crypto API interface specification
  2014-10-16 16:50         ` Stephan Mueller
@ 2014-10-16 17:42           ` Jason Cooper
  0 siblings, 0 replies; 14+ messages in thread
From: Jason Cooper @ 2014-10-16 17:42 UTC (permalink / raw)
  To: Stephan Mueller
  Cc: Grant Likely, Geert Uytterhoeven, Herbert Xu, David S. Miller,
	linux-crypto, linux-kernel

On Thu, Oct 16, 2014 at 06:50:58PM +0200, Stephan Mueller wrote:
> Am Donnerstag, 16. Oktober 2014, 11:06:05 schrieb Jason Cooper:
> 
> Hi Jason,
> 
> > On Thu, Oct 16, 2014 at 09:25:01AM -0400, Jason Cooper wrote:
> > > + Grant, Geert,
> > > 
> > > Stephan has created some great example code for both the kernel crypto
> > > API and the userspace crypto API.  As examples tend to bitrot, I was
> > > wondering if the code could serve as test code.  Then it would have a
> > > triple role: API regression testing, crypto test suite, and reference
> > > implementation.
> > > 
> > > Original patch is here:
> > >   https://lkml.kernel.org/r/7502136.9BkWHTZ0th@myon.chronox.de
> > > 
> > > On Thu, Oct 16, 2014 at 09:19:08AM +0200, Stephan Mueller wrote:
> > > > Am Mittwoch, 15. Oktober 2014, 13:58:00 schrieb Jason Cooper:
> > > > > On Tue, Oct 14, 2014 at 09:46:50PM +0200, Stephan Mueller wrote:
> > ...
> > 
> > > > > Perhaps the userspace API example should be a separate file with this
> > > > > text at the top?  Seems odd having it at the end.  Also, if you copied
> > > > > it from cryptsetup, is the copyright info correct?
> > > > 
> > > > I did not copy it from cryptsetup. I only used it as a basis, especially
> > > > with the data structure handling in _kcapi_cipher_crypt. But you are
> > > > right, I changed the license for the user space by taking the
> > > > cryptsetup license.> 
> > > Ok.  It looks like Geert and Grant took part in the kernel test
> > > unconference, so I'm adding them to the Cc.  I hope they can give us
> > > some pointers as to where we could hook in this code.  Then we can
> > > simply refer to it from the userspace API document.
> > 
> > tools/testing/selftests/crypto would be a good location for the example
> > code in the next version of this patch.  Make sure to take a look at
> > tools/testing/selftests/README.txt.
> 
> Well, I have written a FIPS 140-2 CAVS test harness covering all ciphers NIST 
> is interested. Maybe this can go there?

Assuming you own the code and are willing to license it under and
compatible license, then yes.  I would keep it a separate test from
other crypto tests, though.

There may be some push back wrt it being FIPS 140-2.  But I think it's
worth considering.

thx,

Jason.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] kernel crypto API interface specification
  2014-10-16 13:10 ` Herbert Xu
@ 2014-10-31  3:01   ` Marek Vasut
  2014-10-31  7:23     ` Herbert Xu
  0 siblings, 1 reply; 14+ messages in thread
From: Marek Vasut @ 2014-10-31  3:01 UTC (permalink / raw)
  To: Herbert Xu; +Cc: Stephan Mueller, David S. Miller, linux-crypto, linux-kernel

On Thursday, October 16, 2014 at 03:10:07 PM, Herbert Xu wrote:
> On Tue, Oct 14, 2014 at 09:46:50PM +0200, Stephan Mueller wrote:
> > The update adds a complete interface documentation of the kernel crypto
> > API. All cipher types supported by the kernel crypto API are documented.
> > 
> > In addition, kernel and user space example code is provided. The sample
> > code covers synchronous and asynchronous cipher operation, random
> > number generation and performing hashing as well as encryption and
> > decryption in user space.
> > 
> > Signed-off-by: Stephan Mueller <smueller@chronox.de>
> 
> Thanks for the patch Stephan!
> 
> Marek Vasut <marex@denx.de> has also been working on a set of
> documentation for the crypto API so he might have some comments
> on this.

Sorry for the late reply, thanks for keeping me in the loop.

I can share the last state of the document I wrote. Currently,
it is not possible for me to keep up with my workload and do
anything else, so that's all I can do.

Apologies.

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] kernel crypto API interface specification
  2014-10-31  3:01   ` Marek Vasut
@ 2014-10-31  7:23     ` Herbert Xu
  2014-10-31  9:09       ` Marek Vasut
  0 siblings, 1 reply; 14+ messages in thread
From: Herbert Xu @ 2014-10-31  7:23 UTC (permalink / raw)
  To: Marek Vasut; +Cc: Stephan Mueller, David S. Miller, linux-crypto, linux-kernel

On Fri, Oct 31, 2014 at 04:01:04AM +0100, Marek Vasut wrote:
>
> I can share the last state of the document I wrote. Currently,
> it is not possible for me to keep up with my workload and do
> anything else, so that's all I can do.

Posting your latest revision would be great.

Thanks!
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] kernel crypto API interface specification
  2014-10-31  7:23     ` Herbert Xu
@ 2014-10-31  9:09       ` Marek Vasut
  2014-10-31 13:46         ` Stephan Mueller
  0 siblings, 1 reply; 14+ messages in thread
From: Marek Vasut @ 2014-10-31  9:09 UTC (permalink / raw)
  To: Herbert Xu; +Cc: Stephan Mueller, David S. Miller, linux-crypto, linux-kernel

On Friday, October 31, 2014 at 08:23:53 AM, Herbert Xu wrote:
> On Fri, Oct 31, 2014 at 04:01:04AM +0100, Marek Vasut wrote:
> > I can share the last state of the document I wrote. Currently,
> > it is not possible for me to keep up with my workload and do
> > anything else, so that's all I can do.
> 
> Posting your latest revision would be great.

Please see below, mine is much less complete than Stephan's though
and likely contains some bugs.

Linux Crypto API :: Drivers
===========================

This document outlines how to implement drivers for cryptographic hardware.
The Linux Crypto API supports different types of transformations and we will
explain here how to write drivers for each one of them.

Note: Transformation and algorithm are used interchangably

Note: We support multiple transformation types:
      CIPHER ....... Simple single-block cipher
      BLKCIPHER .... Synchronous multi-block cipher
      ABLKCIPHER ... Asynchronous multi-block cipher
      SHASH ........ Synchronous multi-block hash
      AHASH ........ Asynchronous multi-block hash
      AEAD ......... Authenticated Encryption with Associated Data (MAC)
      COMPRESS ..... Compression
      RNG .......... Random Number Generation

0) Terminology
--------------
 - The transformation implementation is an actual code or interface to hardware
   which implements a certain trasformation with percisely defined behavior.
 - The transformation object (TFM) is an instance of a transformation
   implementation. There can be multiple transformation objects associated with
   a single transformation implementation. Each of those transformation objects
   is held by a crypto API consumer. Transformation object is allocated when a
   crypto API consumer requests a transformation implementation. The consumer
   is then provided with a structure, which contains a transformation object
   (TFM).
 - The transformation context is private data associated with the transformation
   object.

1) The struct crypto_alg description
------------------------------------
 The struct crypto_alg describes a generic Crypto API algorithm and is common
 for all of the transformations. We will first explain what each entry means
 as this is a fundamental building block. We will not follow the order of
 fields as defined in include/linux/crypto.h , but will instead explain them
 in logical order.

  .cra_name .......... Name of the transformation algorithm .
                       - This is the name of the transformation itself. This
                         field is used by the kernel when looking up the
                         providers of particular transformation.
                       - Examples: "md5", "cbc(cast5)", "rfc4106(gcm(aes))"
                       - You can find a good approximation for values of this
                         field by running:
                         $ git grep tcrypt_test crypto/tcrypt.c
  .cra_driver_name ... Name of the transformation provider .
                       - This is the name of the provider of the transformation.
                         This can be any arbitrary value, but in the usual case,
                         this contains the name of the chip or provider and the
                         name of the transformation algorithm.
                       - Examples: "sha1-dcp", "atmel-ecb-aes"
  .cra_priority ...... Priority of this transformation implementation.
                       - In case multiple transformations with same .cra_name
                         are available to the Crypto API, the kernel will use
                         the one with highest .cra_priority .
                       - The software implementations of transformations have
                         this field set to 0 so they are picked only in case
                         no other higher-priority implementation is available.
  .cra_module ........ Owner of this transformation implementation.
                       - Set to THIS_MODULE .

  .cra_blocksize ..... Minimum block size of this transformation.
                       - The size in bytes of the smallest possible unit which
                         can be transformed with this algorithm. The users must
                         respect this value.
                       - In case of HASH transformation, it is possible for a
                         smaller block than .cra_blocksize to be passed to the
                         crypto API for transformation, in case of any other
                         transformation type, an error will be returned upon
                         any attempt to transform smaller than .cra_blocksize
                         chunks.
                       - Examples: SHA1_BLOCK_SIZE, AES_BLOCK_SIZE
                       - You can find predefined values for this field in the
                         kernel source tree with:
                         $ git grep _BLOCK_SIZE include/crypto/
  .cra_alignmask ..... Alignment mask for the input and output data buffer.
                       - The data buffer containing the input data for the
                         algorithm must be aligned to this alignment mask.
                       - The data buffer for the output data must be aligned
                         to this alignment mask.
                       - Note that the Crypto API will do the re-alignment
                         in software, but only under special conditions and
                         there is a performance hit. The re-alignment happens
                         at these occassions for different .cra_u types:
                          cipher: For both input data and output data buffer
                          ahash:  For output hash destination buffer
                          shash:  For output hash destination buffer

                          /* FIXME ... others ? */

                       - This is needed on hardware which is flawed by design
                         and cannot pick data from arbitrary addresses.
  .cra_ctxsize ....... Size of the transformation context.
                       - This is the size of data, which are associated with
                         the transformation object. These data are valid
                         during the entire existence of the transformation
                         object. These data can only ever be modified by the
                         driver.
                       - The driver can retrieve a pointer to these data via
                         the crypto_tfm_ctx() function .

  .cra_type .......... Type of the cryptographic transformation.
                       - This is a pointer to struct crypto_type, which
                         implements callbacks common for all trasnformation
                         types.
                       - There are multiple options:
                           crypto_blkcipher_type .... Sync block cipher
                           crypto_ablkcipher_type ... Async block cipher
                           crypto_ahash_type ........ Async hash
                           crypto_aead_type ......... AEAD
                           crypto_rng_type .......... Random number generator
                       - This field might be empty. In that case, there are
                         no common callbacks. This is the case for:
                           cipher ................... Single-block cipher
                           compress ................. Compression
                           shash .................... Sync hash
  .cra_flags ......... Flags describing this transformation.
                       - See include/linux/crypto.h CRYPTO_ALG_* flags for
                         the flags which go in here. Those are used for
                         fine-tuning the description of the transformation
                         algorithm.
  .cra_u ............. Callbacks implementing the transformation.
                       - This is a union of multiple structures. Depending
                         on the type of transformation selected by .cra_type
                         and .cra_flags above, the associated structure must
                         be filled with callbacks.
                       - There are multiple options:
                           .cipher ....... Cipher
                           .blkcipher .... Sync block cipher
                           .ablkcipher ... Async block cipher
                           .aead ......... AEAD
                           .compress ..... Compression
                           .rng .......... Random number generator
                       - This field might be empty. This is the case for:
                           ahash ......... Async hash
                           shash ......... Sync hash
  .cra_init() ........ Initialize the cryptographic transformation object.
                       - This function is used to initialize the cryptographic
                         transformation object. This function is called
                         only once at the instantiation time, right after the
                         transformation context was allocated.
                       - In case the cryptographic hardware has some special
                         requirements which need to be handled by software,
                         this function shall check for the precise requirement
                         of the transformation and put any software fallbacks
                         in place.
  .cra_exit() ........ Deinitialize the cryptographic transformation object.
                       - This is a counterpart to .cra_init(), used to remove
                         various changes set in .cra_init() .

  .cra_list .......... List header.
                       - This internal field of the crypto API is used as a
                         list head. It allows for this structure to be added
                         into the list of other crypto algorithms.
  .cra_users ......... List of all users of this transformation.
                       - This internal field to the crypto API is used to
                         track all the users which are currently using this
                         particular transformation implementation.
  .cra_refcnt ........ Reference counter for this structure.
                       - This internal field of the crypto API is used to
                         count number of references of this structure so it
                         can be checked when removal is requested.
  .cra_destroy() ..... Deallocate resources of the crypto transformation.
                       - This is used internally by the crypto API. When
                         there are multiple spawns of the algorithm, this
                         is set for all of then and when the refcount
                         reaches zero, this function is called to dealloc
                         all the remaining data.

2) Registering and unregistering transformation
-----------------------------------------------
 There are three distinct types of registration functions in the Crypto API.
 One is used to register a generic cryptographic transformation, while the
 other two are specific to HASH transformations and COMPRESSion . We will
 discuss the latter two in a separate chapter, here we will only look at
 the generic ones.

 The generic registration functions can be found in include/linux/crypto.h
 and their definition can be seen below. The former function registers a
 single transformation, while the latter works on an array of transformation
 descriptions. The latter is useful when registering transformations in bulk.

   int crypto_register_alg(struct crypto_alg *alg);
   int crypto_register_algs(struct crypto_alg *algs, int count);

 The counterparts to those functions are listed below.

   int crypto_unregister_alg(struct crypto_alg *alg);
   int crypto_unregister_algs(struct crypto_alg *algs, int count);

 Notice that both registration and unregistration functions do return a value,
 so make sure to handle errors.

3) Single-block ciphers [CIPHER]
--------------------------------
 Example of transformations: aes, arc4, ...

 This section describes the simplest of all transformation implementations,
 that being the CIPHER type. The CIPHER type is used for transformations
 which operate on exactly one block at a time and there are no dependencies
 between blocks at all.

 3.1) Registration specifics
 ---------------------------
  The registration of [CIPHER] algorithm is specific in that struct crypto_alg
  field .cra_type is empty. The .cra_u.cipher has to be filled in with proper
  callbacks to implement this transformation.

 3.2) Fields in struct cipher_alg explained
 ------------------------------------------
  This section explains the .cra_u.cipher fields and how they are called.
  All of the fields are mandatory and must be filled:

   .cia_min_keysize ... Minimum key size supported by the transformation.
                        - This is the smallest key length supported by this
                          transformation algorithm. This must be set to one
                          of the pre-defined values as this is not hardware
                          specific.
                        - Possible values for this field can be found via:
                          $ git grep "_MIN_KEY_SIZE" include/crypto/
   .cia_max_keysize ... Maximum key size supported by the transformation.
                        - This is the largest key length supported by this
                          transformation algorithm. This must be set to one
                          of the pre-defined values as this is not hardware
                          specific.
                        - Possible values for this field can be found via:
                          $ git grep "_MAX_KEY_SIZE" include/crypto/
   .cia_setkey() ...... Set key for the transformation.
                        - This function is used to either program a supplied
                          key into the hardware or store the key in the
                          transformation context for programming it later. Note
                          that this function does modify the transformation
                          context.
                        - This function can be called multiple times during
                          the existence of the transformation object, so one
                          must make sure the key is properly reprogrammed
                          into the hardware.
                        - This function is also responsible for checking the
                          key length for validity.
                        - In case a software fallback was put in place in
                          the .cra_init() call, this function might need to
                          use the fallback if the algorithm doesn't support
                          all of the key sizes.
   .cia_encrypt() ..... Encrypt a single block.
                        - This function is used to encrypt a single block of
                          data, which must be .cra_blocksize big. This always
                          operates on a full .cra_blocksize and it is not
                          possible to encrypt a block of smaller size. The
                          supplied buffers must therefore also be at least
                          of .cra_blocksize size.
                        - Both the input and output buffers are always aligned
                          to .cra_alignmask . In case either of the input or
                          output buffer supplied by user of the crypto API is
                          not aligned to .cra_alignmask, the crypto API will
                          re-align the buffers. The re-alignment means that a
                          new buffer will be allocated, the data will be copied
                          into the new buffer, then the processing will happen
                          on the new buffer, then the data will be copied back
                          into the original buffer and finally the new buffer
                          will be freed.
                        - In case a software fallback was put in place in
                          the .cra_init() call, this function might need to
                          use the fallback if the algorithm doesn't support
                          all of the key sizes.
                        - In case the key was stored in transformation context,
                          the key might need to be re-programmed into the
                          hardware in this function.
                        - This function shall not modify the transformation
                          context, as this function may be called in parallel
                          with the same transformation object.
   .cia_decrypt() ..... Decrypt a single block.
                        - This is a reverse counterpart to .cia_encrypt(), and
                          the conditions are exactly the same.

  Here are schematics of how these functions are called when operated from
  other part of the kernel. Note that the .cia_setkey() call might happen
  before or after any of these schematics happen, but must not happen during
  any of these are in-flight.

         KEY ---.    PLAINTEXT ---.
                v                 v
          .cia_setkey() -> .cia_encrypt()
                                  |
                                  '-----> CIPHERTEXT

  Please note that a pattern where .cia_setkey() is called multiple times
  is also valid:

  KEY1 --.    PLAINTEXT1 --.         KEY2 --.    PLAINTEXT2 --.
         v                 v                v                 v
   .cia_setkey() -> .cia_encrypt() -> .cia_setkey() -> .cia_encrypt()
                           |                                  |
                           '---> CIPHERTEXT1                  '---> CIPHERTEXT2

4) Multi-block ciphers [BLKCIPHER] [ABLKCIPHER]
-----------------------------------------------
 Example of transformations: cbc(aes), ecb(arc4), ...

 This section describes the multi-block cipher transformation implementations
 for both synchronous [BLKCIPHER] and asynchronous [ABLKCIPHER] case. The
 multi-block ciphers are used for transformations which operate on scatterlists
 of data supplied to the transformation functions. They output the result into
 a scatterlist of data as well.

 4.1) Registration specifics
 ---------------------------
  The registration of [BLKCIPHER] or [ABLKCIPHER] algorithm is one of the most
  standard procedures throughout the crypto API. There are no specifics for
  this case other that re-aligning of input and output buffers does not happen
  automatically within the crypto API, but is the responsibility of the crypto
  API consumer. The crypto API consumer shall use crypto_blkcipher_alignmask()
  or crypto_ablkcipher_alignmask() respectively to determine the needs of the
  transformation object and prepare the scatterlist with data accordingly.

 4.2) Fields in struct blkcipher_alg and struct ablkcipher_alg explained
 -----------------------------------------------------------------------
  This section explains the .cra_u.blkcipher and .cra_u.cra_ablkcipher fields
  and how they are called. Please note that this is very similar to the basic
  CIPHER case for all but minor details. All of the fields but .geniv are
  mandatory and must be filled:

   .min_keysize ... Minimum key size supported by the transformation.
                    - This is the smallest key length supported by this
                      transformation algorithm. This must be set to one
                      of the pre-defined values as this is not hardware
                      specific.
                    - Possible values for this field can be found via:
                      $ git grep "_MIN_KEY_SIZE" include/crypto/
   .max_keysize ... Maximum key size supported by the transformation.
                    - This is the largest key length supported by this
                      transformation algorithm. This must be set to one
                      of the pre-defined values as this is not hardware
                      specific.
                    - Possible values for this field can be found via:
                      $ git grep "_MAX_KEY_SIZE" include/crypto/
   .setkey() ...... Set key for the transformation.
                    - This function is used to either program a supplied
                      key into the hardware or store the key in the
                      transformation context for programming it later. Note
                      that this function does modify the transformation
                      context.
                    - This function can be called multiple times during
                      the existence of the transformation object, so one
                      must make sure the key is properly reprogrammed
                      into the hardware.
                    - This function is also responsible for checking the
                      key length for validity.
                    - In case a software fallback was put in place in
                      the .cra_init() call, this function might need to
                      use the fallback if the algorithm doesn't support
                      all of the key sizes.
   .encrypt() ..... Encrypt a scatterlist of blocks.
                    - This function is used to encrypt the supplied
                      scatterlist containing the blocks of data. The crypto
                      API consumer is responsible for aligning the entries
                      of the scatterlist properly and making sure the
                      chunks are correctly sized.
                    - In case a software fallback was put in place in
                      the .cra_init() call, this function might need to
                      use the fallback if the algorithm doesn't support
                      all of the key sizes.
                    - In case the key was stored in transformation context,
                      the key might need to be re-programmed into the
                      hardware in this function.
                    - This function shall not modify the transformation
                      context, as this function may be called in parallel
                      with the same transformation object.
   .decrypt() ..... Decrypt a single block.
                    - This is a reverse counterpart to .encrypt(), and the
                      conditions are exactly the same.

  Please refer to section 3.2) for schematics of the block cipher usage.
  The usage patterns are exactly the same for [ABLKCIPHER] and [BLKCIPHER]
  as they are for plain [CIPHER].

  4.3) Specifics of asynchronous multi-block cipher
  -------------------------------------------------
  There are a couple of specifics to the [ABLKCIPHER] interface.

  First of all, some of the drivers will want to use the Generic ScatterWalk
  in case the hardware needs to be fed separate chunks of the scatterlist
  which contains the plaintext and will contain the ciphertext. Please refer
  to the section 9.1) of this document on the description and usage of the
  Generic ScatterWalk interface.

  It is recommended to enqueue cryptographic transformation requests into
  generic crypto queues. This allows for these requests to be processed in
  sequence as the cryptographic hardware becomes free. For details on the
  crypto queues, please refer to section 9.2) further down in this text.

5) Hashing [HASH]
-----------------
 Example of transformations: crc32, md5, sha1, sha256,...

 5.1) Registering and unregistering the transformation
 -----------------------------------------------------
  There are multiple ways to register a HASH transformation, depending on
  whether the transformation is synchronous [SHASH] or asynchronous [AHASH]
  and the amount of HASH transformations we are registering. You can find
  the prototypes defined in include/crypto/internal/hash.h :

   int crypto_register_ahash(struct ahash_alg *alg);

   int crypto_register_shash(struct shash_alg *alg);
   int crypto_register_shashes(struct shash_alg *algs, int count);

  The respective counterparts for unregistering the HASH transformation are
  as follows:

   int crypto_unregister_ahash(struct ahash_alg *alg);

   int crypto_unregister_shash(struct shash_alg *alg);
   int crypto_unregister_shashes(struct shash_alg *algs, int count);

 5.2) Common fields of struct shash_alg and ahash_alg explained
 --------------------------------------------------------------
  For definition of these structures, please refer to include/crypto/hash.h .
  We will now explain the meaning of each field:

   .init() ......... Initialize the transformation context.
                     - Intended only to initialize the state of the HASH
                       transformation at the begining. This shall fill in
                       the internal structures used during the entire duration
                       of the whole transformation.
                     - No data processing happens at this point.
   .update() ....... Push chunk of data into the driver for transformation.
                     - This function actually pushes blocks of data from upper
                       layers into the driver, which then passes those to the
                       hardware as seen fit.
                     - This function must not finalize the HASH transformation,
                       this only adds more data into the transformation.
                     - This function shall not modify the transformation
                       context, as this function may be called in parallel
                       with the same transformation object.
                     - Data processing can happen synchronously [SHASH] or
                       asynchronously [AHASH] at this point.
   .final() ....... Retrieve result from the driver.
                     - This function finalizes the transformation and retrieves
                       the resulting hash from the driver and pushes it back to
                       upper layers.
                     - No data processing happens at this point.
   .finup() ........ Combination of update()+final() .
                     - This function is effectively a combination of update()
                       and final() calls issued in sequence.
                     - As some hardware cannot do update() and final()
                       separately, this callback was added to allow such
                       hardware to be used at least by IPsec.
                     - Data processing can happen synchronously [SHASH] or
                       asynchronously [AHASH] at this point.
   .digest() ....... Combination of init()+update()+final() .
                     - This function effectively behaves as the entire chain
                       of operations, init(), update() and final() issued in
                       sequence.
                     - Just like .finup(), this was added for hardware which
                       cannot do even the .finup(), but can only do the whole
                       transformation in one run.
                     - Data processing can happen synchronously [SHASH] or
                       asynchronously [AHASH] at this point.

   .setkey() ....... Set optional key used by the hashing algorithm .
                     - Intended to push optional key used by the hashing
                       algorithm from upper layers into the driver.
                     - This function can store the key in the transformation
                       context or can outright program it into the hardware.
                       In the former case, one must be careful to program
                       the key into the hardware at appropriate time and one
                       must be careful that .setkey() can be called multiple
                       times during the existence of the transformation
                       object.
                     - Not all hashing algorithms do implement this function.
                       -> SHAx/MDx/CRCx do NOT implement this function.
                       -> HMAC(MDx)/HMAC(SHAx) do implement this function.
                     - This function must be called before any other of the
                       init()/update()/final()/finup()/digest() is called.
                     - No data processing happens at this point.

   .export() ....... Export partial state of the transformation .
                     - This function dumps the entire state of the ongoing
                       transformation into a provided block of data so it
                       can be .import()ed back later on.
                     - This is useful in case you want to save partial result
                       of the transformation after processing certain amount
                       of data and reload this partial result multiple times
                       later on for multiple re-use.
                     - No data processing happens at this point.
   .import() ....... Import partial state of the transformation .
                     - This function loads the entire state of the ongoing
                       transformation from a provided block of data so the
                       transformation can continue from this point onward.
                     - No data processing happens at this point.

  Here are schematics of how these functions are called when operated from
  other part of the kernel. Note that the .setkey() call might happen before
  or after any of these schematics happen, but must not happen during any of
  these are in-flight. Please note that calling .init() followed immediatelly
  by .finish() is also a perfectly valid transformation.

   I)   DATA -----------.
                        v
         .init() -> .update() -> .final()      ! .update() might not be called
                     ^    |         |            at all in this scenario.
                     '----'         '---> HASH

   II)  DATA -----------.-----------.
                        v           v
         .init() -> .update() -> .finup()      ! .update() may not be called
                     ^    |         |            at all in this scenario.
                     '----'         '---> HASH

   III) DATA -----------.
                        v
                    .digest()                  ! The entire process is handled
                        |                        by the .digest() call.
                        '---------------> HASH

  Here is a schematic of how the .export()/.import() functions are called when
  used from another part of the kernel.

   KEY--.                 DATA--.
        v                       v                  ! .update() may not be called
    .setkey() -> .init() -> .update() -> .export()   at all in this scenario.
                             ^     |         |
                             '-----'         '--> PARTIAL_HASH

   ----------- other transformations happen here -----------

   PARTIAL_HASH--.   DATA1--.
                 v          v
             .import -> .update() -> .final()     ! .update() may not be called
                         ^    |         |           at all in this scenario.
                         '----'         '--> HASH1

   PARTIAL_HASH--.   DATA2-.
                 v         v
             .import -> .finup()
                           |
                           '---------------> HASH2

 5.3) The struct hash_alg_common fields and it's mirror in struct shash_alg
 --------------------------------------------------------------------------
  This structure defines various size constraints and generic properties of
  the hashing algorithm that is being implemented. Let us first inspect the
  size properties:

   digestsize .... Size of the result of the transformation.
                   - A buffer of this size must be available to the .final()
                     and .finup() calls, so they can store the resulting hash
                     into it.
                   - For various predefined sizes, search include/crypto/
                     using 'git grep _DIGEST_SIZE include/crypto' .
   statesize ..... Size of the block for partial state of the transformation.
                   - A buffer of this size must be passed to the .export()
                     function as it will save the partial state of the
                     transformation into it. On the other side, the .import()
                     function will load the state from a buffer of this size
                     as well.

/* FIXME */

  We will now discuss HASH-specific details of struct crypto_alg . In order
  to understand the rest of the text, please read the section 1) at the
  begining of this documentation first.

/* FIXME ... this needs expanding */

  5.4) Specifics of asynchronous HASH transformation
  --------------------------------------------------
  There are a couple of specifics to the [AHASH] interface.

  First of all, some of the drivers will want to use the Generic ScatterWalk
  in case the hardware needs to be fed separate chunks of the scatterlist
  which contains the input data. The buffer containing the resulting hash will
  always be properly aligned to .cra_alignmask so there is no need to worry
  about this. Please refer to the section 9.1) of this document of the
  description and usage of the Generic ScatterWalk interface.

  It is recommended to enqueue cryptographic transformation requests into
  generic crypto queues. This allows for these requests to be processed in
  sequence as the cryptographic hardware becomes free. For details on the
  crypto queues, please refer to section 9.2) further down in this text.

6) Authenticated Encryption with Associated Data (MAC) [AEAD]
-------------------------------------------------------------

7) Compression [COMPRESS]
-------------------------

8) Random Number Generation [RNG]
---------------------------------

9) Additional helper interfaces
-------------------------------
 This section outlines specific helpers available across various types of
 cryptographic transformation implementations, which are not specific to a
 particular transformation type.

 9.1) Generic ScatterWalk
 ------------------------

 9.2) Crypto Request Queue
 -------------------------

/* FIXME -- others? Multi-queue API ? ... */

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] kernel crypto API interface specification
  2014-10-31  9:09       ` Marek Vasut
@ 2014-10-31 13:46         ` Stephan Mueller
  0 siblings, 0 replies; 14+ messages in thread
From: Stephan Mueller @ 2014-10-31 13:46 UTC (permalink / raw)
  To: Marek Vasut; +Cc: Herbert Xu, David S. Miller, linux-crypto, linux-kernel

Am Freitag, 31. Oktober 2014, 10:09:52 schrieb Marek Vasut:

Hi Marek,

> On Friday, October 31, 2014 at 08:23:53 AM, Herbert Xu wrote:
> > On Fri, Oct 31, 2014 at 04:01:04AM +0100, Marek Vasut wrote:
> > > I can share the last state of the document I wrote. Currently,
> > > it is not possible for me to keep up with my workload and do
> > > anything else, so that's all I can do.
> > 
> > Posting your latest revision would be great.
> 
> Please see below, mine is much less complete than Stephan's though
> and likely contains some bugs.

Thank you for sharing.

I am in the last innings to complete a new patch set. I will see to merge your 
documentation with mine.

The upcoming patchset will cover the following changes:

- split out the user space interface documentation (and fix a bug -- I forgot 
a memset(0) in there)

- keep the "high-level" description in a document in Documentation/crypto/

- put the API function documentation into the header files (I hope that is ok 
that I touch these files to add comments)

-- 
Ciao
Stephan

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2014-10-31 13:46 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-14 19:46 [PATCH] kernel crypto API interface specification Stephan Mueller
2014-10-14 20:00 ` Stephan Mueller
2014-10-15 17:58 ` Jason Cooper
2014-10-16  7:19   ` Stephan Mueller
2014-10-16 13:25     ` Jason Cooper
2014-10-16 13:29       ` Jason Cooper
2014-10-16 15:06       ` Jason Cooper
2014-10-16 16:50         ` Stephan Mueller
2014-10-16 17:42           ` Jason Cooper
2014-10-16 13:10 ` Herbert Xu
2014-10-31  3:01   ` Marek Vasut
2014-10-31  7:23     ` Herbert Xu
2014-10-31  9:09       ` Marek Vasut
2014-10-31 13:46         ` Stephan Mueller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).