Hi,
The following patch set adds documentation files under Documentation/crypto/
covering the high-level description of the API. In addition, it contains
source code comments added to the header files of the kernel crypto API
documenting the API functions.
Changes v2:
* Split out the user space documentation into separate document including
the user space example code
* Change the license of the user space interface code to match the license
of the code that I used as a reference.
* Addition of a precise pointer to the user space interface code reference
code.
* Add a missing memset(0) to the user space example code.
* Move the API function call documentation into the header files in the hope
for a better maintainability.
* Merge the developer-related documentation from Marek Vasut
Stephan Mueller (11):
crypto: Documentation - crypto API high level spec
crypto: Documentation - userspace interface spec
crypto: Documentation - RNG API documentation
crypto: Documentation - AHASH API documentation
crypto: Documentation - SHASH API documentation
crypto: Documentation - documentation of crypto_alg
crypto: Documentation - ABLKCIPHER API documentation
crypto: Documentation - AEAD API documentation
crypto: Documentation - BLKCIPHER API documentation
crypto: Documentation - CIPHER API documentation
crypto: Documentation - HASH API documentation
Documentation/crypto/crypto-API-spec.txt | 721 ++++++++++++++
Documentation/crypto/crypto-API-userspace.txt | 662 +++++++++++++
include/crypto/hash.h | 421 +++++++++
include/crypto/rng.h | 113 +++
include/linux/crypto.h | 1239 ++++++++++++++++++++++++-
5 files changed, 3136 insertions(+), 20 deletions(-)
create mode 100644 Documentation/crypto/crypto-API-spec.txt
create mode 100644 Documentation/crypto/crypto-API-userspace.txt
--
2.1.0
The API function calls exported by the kernel crypto API for
message digests to be used by consumers are documented.
Signed-off-by: Stephan Mueller <[email protected]>
CC: Marek Vasut <[email protected]>
---
include/linux/crypto.h | 117 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 117 insertions(+)
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index b2c3ebb..de44f2d 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -2190,6 +2190,11 @@ static inline void crypto_cipher_decrypt_one(struct crypto_cipher *tfm,
dst, src);
}
+/**
+ * Synchronous message digest API to use the ciphers of type
+ * CRYPTO_ALG_TYPE_HASH (listed as type "hash" in /proc/crypto)
+ */
+
static inline struct crypto_hash *__crypto_hash_cast(struct crypto_tfm *tfm)
{
return (struct crypto_hash *)tfm;
@@ -2202,6 +2207,20 @@ static inline struct crypto_hash *crypto_hash_cast(struct crypto_tfm *tfm)
return __crypto_hash_cast(tfm);
}
+/**
+ * Allocate a cipher handle for a message digest. The returned struct
+ * crypto_hash is the cipher handle that is required for any subsequent
+ * API invocation for that message digest.
+ *
+ * @alg_name is the cra_name / name or cra_driver_name / driver name of the
+ * message digest cipher
+ * @type specifies the type of the cipher (see Documentation/crypto/)
+ * @mask specifies the mask for the cipher (see Documentation/crypto/)
+ *
+ * return value:
+ * allocated cipher handle in case of success
+ * IS_ERR() is true in case of an error, PTR_ERR() returns the error code.
+ */
static inline struct crypto_hash *crypto_alloc_hash(const char *alg_name,
u32 type, u32 mask)
{
@@ -2218,11 +2237,29 @@ static inline struct crypto_tfm *crypto_hash_tfm(struct crypto_hash *tfm)
return &tfm->base;
}
+/**
+ * The referenced message digest handle is zeroized and subsequently
+ * freed.
+ *
+ * @tfm cipher handle to be freed
+ */
static inline void crypto_free_hash(struct crypto_hash *tfm)
{
crypto_free_tfm(crypto_hash_tfm(tfm));
}
+/**
+ * Lookup function to search for the availability of a message digest cipher.
+ *
+ * @alg_name is the cra_name / name or cra_driver_name / driver name of the
+ * message digest cipher
+ * @type specifies the type of the cipher (see Documentation/crypto/)
+ * @mask specifies the mask for the cipher (see Documentation/crypto/)
+
+ * return value:
+ * true when the message digest cipher is known to the kernel crypto API.
+ * false otherwise
+ */
static inline int crypto_has_hash(const char *alg_name, u32 type, u32 mask)
{
type &= ~CRYPTO_ALG_TYPE_MASK;
@@ -2238,6 +2275,15 @@ static inline struct hash_tfm *crypto_hash_crt(struct crypto_hash *tfm)
return &crypto_hash_tfm(tfm)->crt_hash;
}
+/**
+ * The block size for the message digest cipher referenced with the cipher
+ * handle is returned.
+ *
+ * @tfm cipher handle
+ *
+ * return value:
+ * block size of cipher
+ */
static inline unsigned int crypto_hash_blocksize(struct crypto_hash *tfm)
{
return crypto_tfm_alg_blocksize(crypto_hash_tfm(tfm));
@@ -2248,6 +2294,15 @@ static inline unsigned int crypto_hash_alignmask(struct crypto_hash *tfm)
return crypto_tfm_alg_alignmask(crypto_hash_tfm(tfm));
}
+/**
+ * The size for the message digest created by the message digest cipher
+ * referenced with the cipher handle is returned.
+ *
+ * @tfm cipher handle
+ *
+ * return value:
+ * block size of cipher
+ */
static inline unsigned int crypto_hash_digestsize(struct crypto_hash *tfm)
{
return crypto_hash_crt(tfm)->digestsize;
@@ -2268,11 +2323,38 @@ static inline void crypto_hash_clear_flags(struct crypto_hash *tfm, u32 flags)
crypto_tfm_clear_flags(crypto_hash_tfm(tfm), flags);
}
+/**
+ * The call (re-)initializes the message digest referenced by the hash cipher
+ * request handle. Any potentially existing state created by previous
+ * operations is discarded.
+ *
+ * @desc cipher request handle that to be filled by caller as follows:
+ * desc.tfm is filled with the hash cipher handle
+ * desc.flags is filled with either CRYPTO_TFM_REQ_MAY_SLEEP or 0
+ *
+ * return value:
+ * 0 if the message digest initialization was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_hash_init(struct hash_desc *desc)
{
return crypto_hash_crt(desc->tfm)->init(desc);
}
+/**
+ * Updates the message digest state of the cipher handle pointed to by the
+ * hash cipher request handle with the input data pointed to by the
+ * scatter/gather list.
+ *
+ * @desc cipher request handle
+ * @sg scatter / gather list pointing to the data to be added to the message
+ * digest
+ * @nbytes number of bytes to be processed from @sg
+ *
+ * return value:
+ * 0 if the message digest update was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_hash_update(struct hash_desc *desc,
struct scatterlist *sg,
unsigned int nbytes)
@@ -2280,11 +2362,34 @@ static inline int crypto_hash_update(struct hash_desc *desc,
return crypto_hash_crt(desc->tfm)->update(desc, sg, nbytes);
}
+/**
+ * Finalize the message digest operation and create the message digest
+ * based on all data added to the cipher handle. The message digest is placed
+ * into the output buffer.
+ *
+ * @desc cipher request handle
+ * @out message digest output buffer -- The caller must ensure that the out
+ * buffer has a sufficient size (e.g. by using the crypto_hash_digestsize
+ * function).
+ *
+ * return value:
+ * 0 if the message digest creation was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_hash_final(struct hash_desc *desc, u8 *out)
{
return crypto_hash_crt(desc->tfm)->final(desc, 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.
+ *
+ * return value:
+ * 0 if the message digest creation was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_hash_digest(struct hash_desc *desc,
struct scatterlist *sg,
unsigned int nbytes, u8 *out)
@@ -2292,6 +2397,18 @@ static inline int crypto_hash_digest(struct hash_desc *desc,
return crypto_hash_crt(desc->tfm)->digest(desc, sg, nbytes, out);
}
+/**
+ * The caller provided key is set for the message digest cipher. The cipher
+ * handle must point to a keyed hash in order for this function to succeed.
+ *
+ * @tfm cipher handle
+ * @key buffer holding the key
+ * @keylen length of the key in bytes
+ *
+ * return value:
+ * 0 if the setting of the key was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_hash_setkey(struct crypto_hash *hash,
const u8 *key, unsigned int keylen)
{
--
2.1.0
The API function calls exported by the kernel crypto API for
synchronous block ciphers to be used by consumers are documented.
Signed-off-by: Stephan Mueller <[email protected]>
CC: Marek Vasut <[email protected]>
---
include/linux/crypto.h | 268 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 268 insertions(+)
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 12c8a7a..ff15057 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -1593,6 +1593,105 @@ static inline void aead_request_set_assoc(struct aead_request *req,
req->assoclen = assoclen;
}
+/**
+ * Synchronous block cipher API to use the ciphers of type
+ * CRYPTO_ALG_TYPE_BLKCIPHER (listed as type "blkcipher" in /proc/crypto)
+ *
+ * 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.
+ *
+ * The block cipher API allows the use of a complete cipher, i.e. a cipher
+ * consisting of a template (a block chaining mode) and a single block cipher
+ * primitive (e.g. AES).
+ *
+ * The plaintext data buffer and the ciphertext data buffer are pointed to
+ * by using scatter/gather lists. The cipher operation is performed
+ * on all segments of the provided scatter/gather lists.
+ *
+ * The kernel crypto API supports a cipher operation "in-place" which means that
+ * the caller may provide the same scatter/gather list for the plaintext and
+ * cipher text. After the completion of the cipher operation, the plaintext
+ * data is replaced with the ciphertext data in case of an encryption and vice
+ * versa for a decryption. The caller must ensure that the scatter/gather lists
+ * for the output data point to sufficiently large buffers, i.e. multiples of
+ * the block size of the cipher.
+ *
+ * The following code is an example:
+ * #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
+ * 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;
+ *}
+ */
+
static inline struct crypto_blkcipher *__crypto_blkcipher_cast(
struct crypto_tfm *tfm)
{
@@ -1606,6 +1705,20 @@ static inline struct crypto_blkcipher *crypto_blkcipher_cast(
return __crypto_blkcipher_cast(tfm);
}
+/**
+ * Allocate a cipher handle for a block cipher. The returned struct
+ * crypto_blkcipher is the cipher handle that is required for any subsequent
+ * API invocation for that block cipher.
+ *
+ * @alg_name is the cra_name / name or cra_driver_name / driver name of the
+ * blkcipher cipher
+ * @type specifies the type of the cipher (see Documentation/crypto/)
+ * @mask specifies the mask for the cipher (see Documentation/crypto/)
+ *
+ * return value:
+ * allocated cipher handle in case of success
+ * IS_ERR() is true in case of an error, PTR_ERR() returns the error code.
+ */
static inline struct crypto_blkcipher *crypto_alloc_blkcipher(
const char *alg_name, u32 type, u32 mask)
{
@@ -1622,11 +1735,28 @@ static inline struct crypto_tfm *crypto_blkcipher_tfm(
return &tfm->base;
}
+/**
+ * The referenced block cipher handle is zeroized and subsequently freed.
+ *
+ * @tfm cipher handle to be freed
+ */
static inline void crypto_free_blkcipher(struct crypto_blkcipher *tfm)
{
crypto_free_tfm(crypto_blkcipher_tfm(tfm));
}
+/**
+ * Lookup function to search for the availability of a block cipher.
+ *
+ * @alg_name is the cra_name / name or cra_driver_name / driver name of the
+ * block cipher
+ * @type specifies the type of the cipher (see Documentation/crypto/)
+ * @mask specifies the mask for the cipher (see Documentation/crypto/)
+
+ * return value:
+ * true when the block cipher is known to the kernel crypto API.
+ * false otherwise
+ */
static inline int crypto_has_blkcipher(const char *alg_name, u32 type, u32 mask)
{
type &= ~CRYPTO_ALG_TYPE_MASK;
@@ -1636,6 +1766,15 @@ static inline int crypto_has_blkcipher(const char *alg_name, u32 type, u32 mask)
return crypto_has_alg(alg_name, type, mask);
}
+/**
+ * The function returns the name / cra_name of the cipher pointed to with
+ * the cipher handle.
+ *
+ * @tfm cipher handle
+ *
+ * return value:
+ * The character string holding the name of the cipher
+ */
static inline const char *crypto_blkcipher_name(struct crypto_blkcipher *tfm)
{
return crypto_tfm_alg_name(crypto_blkcipher_tfm(tfm));
@@ -1653,11 +1792,30 @@ static inline struct blkcipher_alg *crypto_blkcipher_alg(
return &crypto_blkcipher_tfm(tfm)->__crt_alg->cra_blkcipher;
}
+/**
+ * The size of the IV for the block cipher referenced by the cipher handle is
+ * returned. This IV size may be zero if the cipher does not need an IV.
+ *
+ * @tfm cipher handle
+ *
+ * return value:
+ * IV size in bytes
+ */
static inline unsigned int crypto_blkcipher_ivsize(struct crypto_blkcipher *tfm)
{
return crypto_blkcipher_alg(tfm)->ivsize;
}
+/**
+ * The block size for the block cipher referenced with the cipher handle is
+ * returned. The caller may use that information to allocate appropriate
+ * memory for the data returned by the encryption or decryption operation.
+ *
+ * @tfm cipher handle
+ *
+ * return value:
+ * block size of cipher
+ */
static inline unsigned int crypto_blkcipher_blocksize(
struct crypto_blkcipher *tfm)
{
@@ -1687,6 +1845,23 @@ static inline void crypto_blkcipher_clear_flags(struct crypto_blkcipher *tfm,
crypto_tfm_clear_flags(crypto_blkcipher_tfm(tfm), flags);
}
+/**
+ * The caller provided key is set for the block cipher referenced by the cipher
+ * handle.
+ *
+ * Note, the key length determines the cipher type. Many block ciphers implement
+ * different cipher modes depending on the key size, such as AES-128 vs AES-192
+ * vs. AES-256. When providing a 16 byte key for an AES cipher handle, AES-128
+ * is performed.
+ *
+ * @tfm cipher handle
+ * @key buffer holding the key
+ * @keylen length of the key in bytes
+ *
+ * return value:
+ * 0 if the setting of the key was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_blkcipher_setkey(struct crypto_blkcipher *tfm,
const u8 *key, unsigned int keylen)
{
@@ -1694,6 +1869,26 @@ static inline int crypto_blkcipher_setkey(struct crypto_blkcipher *tfm,
key, keylen);
}
+/**
+ * Encrypt plaintext data using the IV set by the caller with a preceding
+ * call of crypto_blkcipher_set_iv.
+ *
+ * The blkcipher_desc data structure must be filled by the caller and can
+ * reside on the stack. 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
+ *
+ * @desc reference to the block cipher handle with meta data
+ * @dst scatter/gather list that is filled by the cipher operation with the
+ * ciphertext
+ * @src scatter/gather list that holds the plaintext
+ * @nbytes number of bytes of the plaintext to encrypt.
+ *
+ * return value:
+ * 0 if the cipher operation was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_blkcipher_encrypt(struct blkcipher_desc *desc,
struct scatterlist *dst,
struct scatterlist *src,
@@ -1703,6 +1898,27 @@ static inline int crypto_blkcipher_encrypt(struct blkcipher_desc *desc,
return crypto_blkcipher_crt(desc->tfm)->encrypt(desc, dst, src, nbytes);
}
+/**
+ * Encrypt plaintext data with the use of an IV that is solely used for this
+ * cipher operation. Any previously set IV is not used.
+ *
+ * The blkcipher_desc data structure must be filled by the caller and can
+ * reside on the stack. 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
+ *
+ * @desc reference to the block cipher handle with meta data
+ * @dst scatter/gather list that is filled by the cipher operation with the
+ * ciphertext
+ * @src scatter/gather list that holds the plaintext
+ * @nbytes number of bytes of the plaintext to encrypt.
+ *
+ * return value:
+ * 0 if the cipher operation was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_blkcipher_encrypt_iv(struct blkcipher_desc *desc,
struct scatterlist *dst,
struct scatterlist *src,
@@ -1711,6 +1927,24 @@ static inline int crypto_blkcipher_encrypt_iv(struct blkcipher_desc *desc,
return crypto_blkcipher_crt(desc->tfm)->encrypt(desc, dst, src, nbytes);
}
+/**
+ * Decrypt ciphertext data using the IV set by the caller with a preceding
+ * call of crypto_blkcipher_set_iv.
+ *
+ * The blkcipher_desc data structure must be filled by the caller as documented
+ * for the crypto_blkcipher_encrypt call above.
+ *
+ * @desc reference to the block cipher handle with meta data
+ * @dst scatter/gather list that is filled by the cipher operation with the
+ * plaintext
+ * @src scatter/gather list that holds the ciphertext
+ * @nbytes number of bytes of the ciphertext to decrypt.
+ *
+ * return value:
+ * 0 if the cipher operation was successful
+ * < 0 if an error occurred
+ *
+ */
static inline int crypto_blkcipher_decrypt(struct blkcipher_desc *desc,
struct scatterlist *dst,
struct scatterlist *src,
@@ -1720,6 +1954,23 @@ static inline int crypto_blkcipher_decrypt(struct blkcipher_desc *desc,
return crypto_blkcipher_crt(desc->tfm)->decrypt(desc, dst, src, nbytes);
}
+/**
+ * Decrypt ciphertext data with the use of an IV that is solely used for this
+ * cipher operation. Any previously set IV is not used.
+ *
+ * The blkcipher_desc data structure must be filled by the caller as documented
+ * for the crypto_blkcipher_encrypt_iv call above.
+ *
+ * @desc reference to the block cipher handle with meta data
+ * @dst scatter/gather list that is filled by the cipher operation with the
+ * plaintext
+ * @src scatter/gather list that holds the ciphertext
+ * @nbytes number of bytes of the ciphertext to decrypt.
+ *
+ * return value:
+ * 0 if the cipher operation was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_blkcipher_decrypt_iv(struct blkcipher_desc *desc,
struct scatterlist *dst,
struct scatterlist *src,
@@ -1728,12 +1979,29 @@ static inline int crypto_blkcipher_decrypt_iv(struct blkcipher_desc *desc,
return crypto_blkcipher_crt(desc->tfm)->decrypt(desc, dst, src, nbytes);
}
+/**
+ * The caller provided IV is set for the block cipher referenced by the cipher
+ * handle.
+ *
+ * @tfm cipher handle
+ * @src buffer holding the IV
+ * @len length of the IV in bytes
+ */
static inline void crypto_blkcipher_set_iv(struct crypto_blkcipher *tfm,
const u8 *src, unsigned int len)
{
memcpy(crypto_blkcipher_crt(tfm)->iv, src, len);
}
+/**
+ * The caller can obtain the IV set for the block cipher referenced by the
+ * cipher handle and store it into the user-provided buffer. If the buffer
+ * has an insufficient space, the IV is truncated to fit the buffer.
+ *
+ * @tfm cipher handle
+ * @dst buffer filled with the IV
+ * @len length of the buffer dst
+ */
static inline void crypto_blkcipher_get_iv(struct crypto_blkcipher *tfm,
u8 *dst, unsigned int len)
{
--
2.1.0
The API function calls exported by the kernel crypto API for SHASHes
to be used by consumers are documented.
Signed-off-by: Stephan Mueller <[email protected]>
CC: Marek Vasut <[email protected]>
---
include/crypto/hash.h | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 197 insertions(+)
diff --git a/include/crypto/hash.h b/include/crypto/hash.h
index 0d43dbc..7b3a621 100644
--- a/include/crypto/hash.h
+++ b/include/crypto/hash.h
@@ -484,6 +484,33 @@ static inline void ahash_request_set_crypt(struct ahash_request *req,
req->result = result;
}
+/**
+ * Synchronous message digest API to use the ciphers of type
+ * CRYPTO_ALG_TYPE_SHASH (listed as type "shash" in /proc/crypto)
+ *
+ * Considering the discussion of the state maintenance for the synchronous
+ * 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.
+ *
+ * The synchronous message digest API can store user-related context in in its
+ * shash_desc request data structure.
+ */
+
+/**
+ * Allocate a cipher handle for a message digest. The returned struct
+ * crypto_shash is the cipher handle that is required for any subsequent
+ * API invocation for that message digest.
+ *
+ * @alg_name is the cra_name / name or cra_driver_name / driver name of the
+ * message digest cipher
+ * @type specifies the type of the cipher (see Documentation/crypto/)
+ * @mask specifies the mask for the cipher (see Documentation/crypto/)
+ *
+ * return value:
+ * allocated cipher handle in case of success
+ * IS_ERR() is true in case of an error, PTR_ERR() returns the error code.
+ */
struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type,
u32 mask);
@@ -492,6 +519,12 @@ static inline struct crypto_tfm *crypto_shash_tfm(struct crypto_shash *tfm)
return &tfm->base;
}
+/**
+ * The referenced message digest handle is zeroized and subsequently
+ * freed.
+ *
+ * @tfm cipher handle to be freed
+ */
static inline void crypto_free_shash(struct crypto_shash *tfm)
{
crypto_destroy_tfm(tfm, crypto_shash_tfm(tfm));
@@ -503,6 +536,15 @@ static inline unsigned int crypto_shash_alignmask(
return crypto_tfm_alg_alignmask(crypto_shash_tfm(tfm));
}
+/**
+ * The block size for the message digest cipher referenced with the cipher
+ * handle is returned.
+ *
+ * @tfm cipher handle
+ *
+ * return value:
+ * block size of cipher
+ */
static inline unsigned int crypto_shash_blocksize(struct crypto_shash *tfm)
{
return crypto_tfm_alg_blocksize(crypto_shash_tfm(tfm));
@@ -518,6 +560,15 @@ static inline struct shash_alg *crypto_shash_alg(struct crypto_shash *tfm)
return __crypto_shash_alg(crypto_shash_tfm(tfm)->__crt_alg);
}
+/**
+ * The size for the message digest created by the message digest cipher
+ * referenced with the cipher handle is returned.
+ *
+ * @tfm cipher handle
+ *
+ * return value:
+ * block size of cipher
+ */
static inline unsigned int crypto_shash_digestsize(struct crypto_shash *tfm)
{
return crypto_shash_alg(tfm)->digestsize;
@@ -543,6 +594,60 @@ static inline void crypto_shash_clear_flags(struct crypto_shash *tfm, u32 flags)
crypto_tfm_clear_flags(crypto_shash_tfm(tfm), flags);
}
+/**
+ * The size of the operational state the cipher needs during operation is
+ * returned for the hash referenced with the cipher handle. This size is
+ * required to calculate the memory requirements to allow the caller allocating
+ * sufficient memory for operational state.
+ *
+ * The operational state is defined with struct shash_desc where the size of
+ * that data structure is to be calculated as
+ * sizeof(struct shash_desc) + crypto_shash_descsize(alg)
+ *
+ * @tfm cipher handle
+ *
+ * return value:
+ * size of the operational state
+ *
+ * The following example code shall illustrate the use of the operational
+ * state 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(struct crypto_shash *alg,
+ * const unsigned char *data, unsigned int datalen,
+ * unsigned char *digest) {
+ * struct sdesc *sdesc;
+ * int ret;
+ *
+ * sdesc = init_sdesc(alg);
+ * 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;
+ *}
+ */
static inline unsigned int crypto_shash_descsize(struct crypto_shash *tfm)
{
return tfm->descsize;
@@ -553,29 +658,121 @@ static inline void *shash_desc_ctx(struct shash_desc *desc)
return desc->__ctx;
}
+/**
+ * The caller provided key is set for the message digest cipher. The cipher
+ * handle must point to a keyed hash in order for this function to succeed.
+ *
+ * @tfm cipher handle
+ * @key buffer holding the key
+ * @keylen length of the key in bytes
+ *
+ * return value:
+ * 0 if the setting of the key was successful
+ * < 0 if an error occurred
+ */
int crypto_shash_setkey(struct crypto_shash *tfm, const u8 *key,
unsigned int keylen);
+
+/**
+ * This function is a "short-hand" for the function calls of crypto_shash_init,
+ * crypto_shash_update and crypto_shash_final. The parameters have the same
+ * meaning as discussed for those separate three functions.
+ *
+ * return value:
+ * 0 if the message digest creation was successful
+ * < 0 if an error occurred
+ */
int crypto_shash_digest(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out);
+/**
+ * This function exports the hash state of the operational state handle into the
+ * caller-allocated output buffer out which must have sufficient size (e.g. by
+ * calling crypto_shash_descsize).
+ *
+ * @desc reference to the operational state handle whose state is exported
+ * @out output buffer of sufficient size that can hold the hash state
+ *
+ * return value:
+ * 0 if the export creation was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_shash_export(struct shash_desc *desc, void *out)
{
return crypto_shash_alg(desc->tfm)->export(desc, out);
}
+/**
+ * This function imports the hash state into the operational state handle from
+ * the input buffer. That buffer should have been generated with the
+ * crypto_ahash_export function.
+ *
+ * @desc reference to the operational state handle the state imported into
+ * @in buffer holding the state
+ *
+ * return value:
+ * 0 if the import was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_shash_import(struct shash_desc *desc, const void *in)
{
return crypto_shash_alg(desc->tfm)->import(desc, in);
}
+/**
+ * The call (re-)initializes the message digest referenced by the
+ * operational state handle. Any potentially existing state created by
+ * previous operations is discarded.
+ *
+ * @desc operational state handle that is already filled
+ *
+ * return value:
+ * 0 if the message digest initialization was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_shash_init(struct shash_desc *desc)
{
return crypto_shash_alg(desc->tfm)->init(desc);
}
+/**
+ * Updates the message digest state of the operational state handle.
+ *
+ * @desc operational state handle that is already initialized
+ * @data input data to be added to the message digest
+ * @len length of the input data
+ *
+ * return value:
+ * 0 if the message digest update was successful
+ * < 0 if an error occurred
+ */
int crypto_shash_update(struct shash_desc *desc, const u8 *data,
unsigned int len);
+
+/**
+ * Finalize the message digest operation and create the message digest
+ * based on all data added to the cipher handle. The message digest is placed
+ * into the output buffer. The caller must ensure that the output buffer is
+ * large enough by using crypto_shash_digestsize.
+ *
+ * @desc operational state handle that is already filled with data
+ * @out output buffer filled with the message digest
+ *
+ * return value:
+ * 0 if the message digest creation was successful
+ * < 0 if an error occurred
+ */
int crypto_shash_final(struct shash_desc *desc, u8 *out);
+
+/**
+ * This function is a "short-hand" for the function calls of
+ * crypto_shash_update and crypto_shash_final. The parameters have the same
+ * meaning as discussed for those separate functions.
+ *
+ * return value:
+ * 0 if the message digest creation was successful
+ * < 0 if an error occurred
+ */
int crypto_shash_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out);
--
2.1.0
The API function calls exported by the kernel crypto API for
asynchronous block ciphers to be used by consumers are documented.
Signed-off-by: Stephan Mueller <[email protected]>
CC: Marek Vasut <[email protected]>
---
include/linux/crypto.h | 349 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 349 insertions(+)
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index e1a84fd..67acda4 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -698,6 +698,190 @@ static inline u32 crypto_skcipher_mask(u32 mask)
return mask;
}
+/**
+ * Asynchronous block cipher API to use the ciphers of type
+ * CRYPTO_ALG_TYPE_ABLKCIPHER (listed as type "ablkcipher" in /proc/crypto)
+ *
+ * Asynchronous cipher operations imply that the function invocation for a
+ * cipher request returns immediately before the completion of the operation.
+ * The cipher request is scheduled as a separate kernel thread and therefore
+ * load-balanced on the different CPUs via the process scheduler. To allow
+ * the kernel crypto API to inform the caller about the completion of a cipher
+ * request, the caller must provide a callback function. That function is
+ * invoked with the cipher handle when the request completes.
+ *
+ * To support the asynchronous operation, additional information than just the
+ * cipher handle must be supplied to the kernel crypto API. That additional
+ * information is given by filling in the ablkcipher_request data structure.
+ *
+ * For the asynchronous block cipher API, the state is maintained with the tfm
+ * cipher handle. A single tfm can be used across multiple calls and in
+ * parallel. For asynchronous block cipher calls, context data supplied and
+ * only used by the caller can be referenced the request data structure in
+ * addition to the IV used for the cipher request. The maintenance of such
+ * state information would be important for a crypto driver implementer to
+ * have, because when calling the callback function upon completion of the
+ * cipher operation, that callback function may need some information about
+ * which operation just finished if it invoked multiple in parallel. This
+ * state information is unused by the kernel crypto API.
+ *
+ * Example code
+ *
+ *#include <linux/crypto.h>
+ *#include <linux/scatterlist.h>
+ *#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 cipher operation
+ *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;
+ *}
+ */
+
+/**
+ * Allocate a cipher handle for an ablkcipher. The returned struct
+ * crypto_ablkcipher is the cipher handle that is required for any subsequent
+ * API invocation for that ablkcipher.
+ *
+ * @alg_name is the cra_name / name or cra_driver_name / driver name of the
+ * ablkcipher cipher
+ * @type specifies the type of the cipher (see Documentation/crypto/)
+ * @mask specifies the mask for the cipher (see Documentation/crypto/)
+ *
+ * return value:
+ * allocated cipher handle in case of success
+ * IS_ERR() is true in case of an error, PTR_ERR() returns the error code.
+ */
struct crypto_ablkcipher *crypto_alloc_ablkcipher(const char *alg_name,
u32 type, u32 mask);
@@ -707,11 +891,28 @@ static inline struct crypto_tfm *crypto_ablkcipher_tfm(
return &tfm->base;
}
+/**
+ * The referenced ablkcipher handle is zeroized and subsequently freed.
+ *
+ * @tfm cipher handle to be freed
+ */
static inline void crypto_free_ablkcipher(struct crypto_ablkcipher *tfm)
{
crypto_free_tfm(crypto_ablkcipher_tfm(tfm));
}
+/**
+ * Lookup function to search for the availability of an ablkcipher.
+ *
+ * @alg_name is the cra_name / name or cra_driver_name / driver name of the
+ * ablkcipher
+ * @type specifies the type of the cipher (see Documentation/crypto/)
+ * @mask specifies the mask for the cipher (see Documentation/crypto/)
+ *
+ * return value:
+ * true when the ablkcipher is known to the kernel crypto API.
+ * false otherwise
+ */
static inline int crypto_has_ablkcipher(const char *alg_name, u32 type,
u32 mask)
{
@@ -725,12 +926,31 @@ static inline struct ablkcipher_tfm *crypto_ablkcipher_crt(
return &crypto_ablkcipher_tfm(tfm)->crt_ablkcipher;
}
+/**
+ * The size of the IV for the ablkcipher referenced by the cipher handle is
+ * returned. This IV size may be zero if the cipher does not need an IV.
+ *
+ * @tfm cipher handle
+ *
+ * return value:
+ * IV size in bytes
+ */
static inline unsigned int crypto_ablkcipher_ivsize(
struct crypto_ablkcipher *tfm)
{
return crypto_ablkcipher_crt(tfm)->ivsize;
}
+/**
+ * The block size for the ablkcipher referenced with the cipher handle is
+ * returned. The caller may use that information to allocate appropriate
+ * memory for the data returned by the encryption or decryption operation
+ *
+ * @tfm cipher handle
+ *
+ * return value:
+ * block size of cipher
+ */
static inline unsigned int crypto_ablkcipher_blocksize(
struct crypto_ablkcipher *tfm)
{
@@ -760,6 +980,23 @@ static inline void crypto_ablkcipher_clear_flags(struct crypto_ablkcipher *tfm,
crypto_tfm_clear_flags(crypto_ablkcipher_tfm(tfm), flags);
}
+/**
+ * The caller provided key is set for the ablkcipher referenced by the cipher
+ * handle.
+ *
+ * Note, the key length determines the cipher type. Many block ciphers implement
+ * different cipher modes depending on the key size, such as AES-128 vs AES-192
+ * vs. AES-256. When providing a 16 byte key for an AES cipher handle, AES-128
+ * is performed.
+ *
+ * @tfm cipher handle
+ * @key buffer holding the key
+ * @keylen length of the key in bytes
+ *
+ * return value:
+ * 0 if the setting of the key was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
const u8 *key, unsigned int keylen)
{
@@ -768,12 +1005,33 @@ static inline int crypto_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
return crt->setkey(crt->base, key, keylen);
}
+/**
+ * Return the crypto_ablkcipher handle when furnishing an ablkcipher_request
+ * data structure.
+ *
+ * @req ablkcipher_request out of which the cipher handle is to be obtained
+ *
+ * return value:
+ * crypto_ablkcipher handle
+ */
static inline struct crypto_ablkcipher *crypto_ablkcipher_reqtfm(
struct ablkcipher_request *req)
{
return __crypto_ablkcipher_cast(req->base.tfm);
}
+/**
+ * Encrypt plaintext data using the ablkcipher_request handle. That data
+ * structure and how it is filled with data is discussed with the
+ * ablkcipher_request_* functions.
+ *
+ * @req reference to the ablkcipher_request handle that holds all information
+ * needed to perform the cipher operation
+ *
+ * return value:
+ * 0 if the cipher operation was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_ablkcipher_encrypt(struct ablkcipher_request *req)
{
struct ablkcipher_tfm *crt =
@@ -781,6 +1039,18 @@ static inline int crypto_ablkcipher_encrypt(struct ablkcipher_request *req)
return crt->encrypt(req);
}
+/**
+ * Decrypt ciphertext data using the ablkcipher_request handle. That data
+ * structure and how it is filled with data is discussed with the
+ * ablkcipher_request_* functions.
+ *
+ * @req reference to the ablkcipher_request handle that holds all information
+ * needed to perform the cipher operation
+ *
+ * return value:
+ * 0 if the cipher operation was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_ablkcipher_decrypt(struct ablkcipher_request *req)
{
struct ablkcipher_tfm *crt =
@@ -788,12 +1058,36 @@ static inline int crypto_ablkcipher_decrypt(struct ablkcipher_request *req)
return crt->decrypt(req);
}
+/**
+ * The ablkcipher_request data structure contains all pointers to data
+ * required for the asynchronous cipher operation. This includes the cipher
+ * handle (which can be used by multiple ablkcipher_request instances), pointer
+ * to plaintext and ciphertext, asynchronous callback function, etc. It acts
+ * as a handle to the ablkcipher_request_* API calls in a similar way as
+ * ablkcipher handle to the crypto_ablkcipher_* API calls.
+ */
+
+/**
+ * Return the size of the ablkcipher_request data structure to the caller.
+ *
+ * @tfm cipher handle
+ *
+ * return value:
+ * number of bytes
+ */
static inline unsigned int crypto_ablkcipher_reqsize(
struct crypto_ablkcipher *tfm)
{
return crypto_ablkcipher_crt(tfm)->reqsize;
}
+/**
+ * Allow the caller to replace the existing ablkcipher handle in the request
+ * data structure with a different one.
+ *
+ * @req request handle to be modified
+ * @tfm cipher handle that shall be added to the request handle
+ */
static inline void ablkcipher_request_set_tfm(
struct ablkcipher_request *req, struct crypto_ablkcipher *tfm)
{
@@ -806,6 +1100,18 @@ static inline struct ablkcipher_request *ablkcipher_request_cast(
return container_of(req, struct ablkcipher_request, base);
}
+/**
+ * Allocate the request data structure that must be used with the ablkcipher
+ * encrypt and decrypt API calls. During the allocation, the provided ablkcipher
+ * handle is registered in the request data structure.
+ *
+ * @tfm cipher handle to be registered with the request
+ * @gfp memory allocation flag that is handed to kmalloc by the API call.
+ *
+ * return value:
+ * allocated request handle in case of success
+ * IS_ERR() is true in case of an error, PTR_ERR() returns the error code.
+ */
static inline struct ablkcipher_request *ablkcipher_request_alloc(
struct crypto_ablkcipher *tfm, gfp_t gfp)
{
@@ -820,11 +1126,40 @@ static inline struct ablkcipher_request *ablkcipher_request_alloc(
return req;
}
+/**
+ * The referenced request data structure is zeroized and subsequently freed.
+ *
+ * @req request data structure cipher handle to be freed
+ */
static inline void ablkcipher_request_free(struct ablkcipher_request *req)
{
kzfree(req);
}
+/**
+ * Setting the callback function that is triggered once the cipher operation
+ * completes
+ *
+ * The callback function is registered with the ablkcipher_request handle and
+ * must comply with the following template:
+ *
+ * void callback_function(struct crypto_async_request *req, int error)
+ *
+ * @req request handle
+ * @flags specify zero or an ORing 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
+ * @compl callback function pointer to be registered with the request handle
+ * @data 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 data structure provided to the callback function.
+ */
static inline void ablkcipher_request_set_callback(
struct ablkcipher_request *req,
u32 flags, crypto_completion_t compl, void *data)
@@ -834,6 +1169,20 @@ static inline void ablkcipher_request_set_callback(
req->base.flags = flags;
}
+/**
+ * Setting the source data and destination data 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.
+ *
+ * @req request handle
+ * @src source scatter / gather list
+ * @dst destination scatter / gather list
+ * @nbytes number of bytes to process from @src
+ * @iv IV for the cipher operation which must comply with the IV size defined
+ * by crypto_ablkcipher_ivsize
+ */
static inline void ablkcipher_request_set_crypt(
struct ablkcipher_request *req,
struct scatterlist *src, struct scatterlist *dst,
--
2.1.0
The API function calls exported by the kernel crypto API for RNGs to
be used by consumers are documented.
Signed-off-by: Stephan Mueller <[email protected]>
CC: Marek Vasut <[email protected]>
---
include/crypto/rng.h | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 113 insertions(+)
diff --git a/include/crypto/rng.h b/include/crypto/rng.h
index c93f9b9..83c4238 100644
--- a/include/crypto/rng.h
+++ b/include/crypto/rng.h
@@ -20,11 +20,68 @@ extern struct crypto_rng *crypto_default_rng;
int crypto_get_default_rng(void);
void crypto_put_default_rng(void);
+/**
+ * Random number generator API to use the ciphers of type
+ * CRYPTO_ALG_TYPE_RNG (listed as type "rng" in /proc/crypto)
+ *
+ * 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;
+ *}
+ */
+
static inline struct crypto_rng *__crypto_rng_cast(struct crypto_tfm *tfm)
{
return (struct crypto_rng *)tfm;
}
+/**
+ * Allocate a cipher handle for a random number generator. The returned struct
+ * crypto_rng is the cipher handle that is required for any subsequent
+ * API invocation for 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 cra_name / name or cra_driver_name / driver name of the
+ * message digest cipher
+ * @type specifies the type of the cipher (see Documentation/crypto/)
+ * @mask specifies the mask for the cipher (see Documentation/crypto/)
+ *
+ * return value:
+ * allocated cipher handle in case of success
+ * IS_ERR() is true in case of an error, PTR_ERR() returns the error code.
+ */
static inline struct crypto_rng *crypto_alloc_rng(const char *alg_name,
u32 type, u32 mask)
{
@@ -40,6 +97,14 @@ static inline struct crypto_tfm *crypto_rng_tfm(struct crypto_rng *tfm)
return &tfm->base;
}
+/**
+ * Return the generic name (cra_name) of the initialized random number generator
+ *
+ * @tfm cipher handle
+ *
+ * return value:
+ * generic name string
+ */
static inline struct rng_alg *crypto_rng_alg(struct crypto_rng *tfm)
{
return &crypto_rng_tfm(tfm)->__crt_alg->cra_rng;
@@ -50,23 +115,71 @@ static inline struct rng_tfm *crypto_rng_crt(struct crypto_rng *tfm)
return &crypto_rng_tfm(tfm)->crt_rng;
}
+/**
+ * The referenced random number generator handle is zeroized and subsequently
+ * freed.
+ *
+ * @tfm cipher handle to be freed
+ */
static inline void crypto_free_rng(struct crypto_rng *tfm)
{
crypto_free_tfm(crypto_rng_tfm(tfm));
}
+/**
+ * This function fills the caller-allocated buffer with random numbers using the
+ * random number generator referenced by the cipher handle.
+ *
+ * @tfm cipher handle
+ * @rdata output buffer holding the random numbers
+ * @dlen length of the output buffer
+ *
+ * return value:
+ * > 0 function was successful and returns the number of generated bytes
+ * < 0 if an error occurred
+ */
static inline int crypto_rng_get_bytes(struct crypto_rng *tfm,
u8 *rdata, unsigned int dlen)
{
return crypto_rng_crt(tfm)->rng_gen_random(tfm, rdata, dlen);
}
+/**
+ * The reset function completely re-initializes the random number generator
+ * referenced by the cipher handle by clearing the current state. The new state
+ * is initialized with the caller provided seed or automatically, depending
+ * on the random number generator type (the ANSI X9.31 RNG requires
+ * caller-provided seed, the SP800-90A DRBGs perform an automatic seeding).
+ * The seed is provided with the. The provided seed should have the length of
+ * the seed size defined for the random number generator as defined by
+ * crypto_rng_seedsize.
+ *
+ * @tfm cipher handle
+ * @seed seed input data
+ * @slen length of the seed input data
+ *
+ * return value:
+ * 0 if the setting of the key was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_rng_reset(struct crypto_rng *tfm,
u8 *seed, unsigned int slen)
{
return crypto_rng_crt(tfm)->rng_reset(tfm, seed, slen);
}
+/**
+ * The function returns the seed size for the random number generator
+ * referenced by the cipher handle. This value may be zero if the random
+ * number generator does not implement or require a reseeding. For example,
+ * the SP800-90A DRBGs implement an automated reseeding after reaching a
+ * pre-defined threshold.
+ *
+ * @tfm cipher handle
+ *
+ * return value:
+ * seed size for the random number generator
+ */
static inline int crypto_rng_seedsize(struct crypto_rng *tfm)
{
return crypto_rng_alg(tfm)->seedsize;
--
2.1.0
The design of the kernel crypto API as well as hints to program with
the kernel crypto API are given.
The documentation contains:
* design aspects of crypto API
* develper specific hints
* references to the API function description
Signed-off-by: Stephan Mueller <[email protected]>
CC: Marek Vasut <[email protected]>
---
Documentation/crypto/crypto-API-spec.txt | 721 +++++++++++++++++++++++++++++++
1 file changed, 721 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..8a24c98
--- /dev/null
+++ b/Documentation/crypto/crypto-API-spec.txt
@@ -0,0 +1,721 @@
+Kernel Crypto API Interface Specification
+=========================================
+
+The kernel crypto API offers a rich set of cryptographic ciphers as well as
+other data transformation mechanisms and methods to invoke these. 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 its
+structure is given. Based on the architecture, the API can be separated into
+different components. Following the architecture specification, hints to
+developers of ciphers are provided. Pointers to the API function call
+documentation are given at the end.
+
+The kernel crypto API refers to all algorithms as "transformation". 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:
+
+ * consumers requesting cryptographic services
+
+ * data transformation implementations (typically ciphers) that
+ can be called by consumers using the kernel crypto API
+
+This specification is intended for consumers of the kernel crypto API as well
+as for developers implementing ciphers. This API specification, however, does
+not discusses 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).
+
+Note: The terms "transformation" and cipher algorithm are used interchangably.
+
+
+Terminology
+-----------
+
+The transformation implementation is an actual code or interface to hardware
+which implements a certain transformation with precisely 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 or another transformation. 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.
+
+
+Kernel Crypto API Architecture
+==============================
+
+Cipher algorithm 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 single block ciphers and
+message digests. In addition, the kernel crypto API provides numerous
+"templates" that can be used in conjunction with the single block ciphers and
+message digests. Templates include all types of block chaining mode, the HMAC
+mechanism, etc.
+
+Single block ciphers and message digests can either be directly used by a
+caller or invoked together with a template to form multi-block ciphers or keyed
+message digests.
+
+A single block cipher may even be called with multiple templates. However,
+templates cannot be used without a single cipher.
+
+
+Synchronous and asynchronous operation
+--------------------------------------
+
+The kernel crypto API provides synchronous and asynchronous API operations.
+
+When using the synchronous API operation, 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 operation, the set
+of API calls is small and conceptually 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(single block cipher)
+
+where "template" and "single block cipher" is the aforementioned template and
+single block cipher, respectively. If applicable, additional templates may
+enclose other templates, such as
+
+ template1(template2(single block cipher)))
+
+The kernel crypto API may provide multiple implementations of a template or a
+single block cipher. For example, AES on newer Intel 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 are listed. However, that list does not specify all
+possible permutations of templates and ciphers. 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 consumers 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 single block ciphers that may be used with an
+ additional template
+ - 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
+ and handling as it is specific to the given cipher
+
+
+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-192 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 Raw block cipher
+ * CRYPTO_ALG_TYPE_COMPRESS Compression
+ * CRYPTO_ALG_TYPE_AEAD Authenticated Encryption with Associated Data (MAC)
+ * CRYPTO_ALG_TYPE_BLKCIPHER Synchronous multi-block cipher
+ * CRYPTO_ALG_TYPE_ABLKCIPHER Asynchronous multi-block cipher
+ * CRYPTO_ALG_TYPE_GIVCIPHER
+ * CRYPTO_ALG_TYPE_DIGEST Raw message digest
+ * CRYPTO_ALG_TYPE_HASH Alias for CRYPTO_ALG_TYPE_DIGEST
+ * CRYPTO_ALG_TYPE_SHASH Synchronous multi-block hash
+ * CRYPTO_ALG_TYPE_AHASH Asynchronous multi-block hash
+ * CRYPTO_ALG_TYPE_RNG Random Number Generation
+ * 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.
+
+When the caller provides a mask and type specification, the caller limits the
+kernel crypto API?s search for a suitable cipher implementation for the given
+cipher name. That means, even when a caller uses a cipher name that exists
+during its initialization call, the kernel crypto API may not select it due
+to the used type and mask field.
+
+
+Developing Cipher Algorithms
+============================
+
+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.
+
+The bulk registration / unregistration functions require that struct crypto_alg
+is an array of count size. These functions simply loop over that array and
+register / unregister each individual algorithm. If an error occurs, the
+loop is terminated at the offending algorithm definition. That means, the
+algorithms prior to the offending algorithm are successfully registered.
+
+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.
+
+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.
+
+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
+
+
+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.
+
+Registration specifics
+......................
+
+The registration of [BLKCIPHER] or [ABLKCIPHER] algorithms 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.
+
+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 the single block cipher description for schematics of the block
+cipher usage. The usage patterns are exactly the same for [ABLKCIPHER] and
+[BLKCIPHER] as they are for plain [CIPHER].
+
+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
+below for a 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.
+
+
+Hashing [HASH]
+--------------
+
+Example of transformations: crc32, md5, sha1, sha256,...
+
+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);
+
+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
+
+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.
+
+
+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.
+
+
+Single block cipher API
+=======================
+
+See source code comments for the *_cipher* calls in include/linux/crypto.h.
+
+
+Synchronous block cipher API
+============================
+
+See source code comments for the *_blkcipher* calls in include/linux/crypto.h.
+
+
+Asynchronous block cipher API
+=============================
+
+See source code comments for the *_ablkcipher* calls and "ablkcipher_request_*
+calls in include/linux/crypto.h.
+
+
+Synchronous message digest API
+==============================
+
+See source code comments for the *_hash* calls in include/linux/crypto.h.
+
+
+Synchronous message digest API with caller-accessible state space
+=================================================================
+
+See source code comments for the *_shash* calls in include/crypto/hash.h.
+
+
+Asynchronous message digest API
+===============================
+
+See source code comments for the *_ahash* calls and "ahash_request_*
+calls in include/crypto/hash.h.
+
+
+Random number generation API
+============================
+
+See source code comments for the *_rng* calls in include/crypto/hash.h.
+
+
+AEAD asynchronous cipher API
+============================
+
+See source code comments for the *_aead* calls and "aead_request_*
+calls in include/linux/crypto.h.
+
+
+Authors
+=======
+
+Stephan Mueller <[email protected]>
+Marek Vasut <[email protected]>
--
2.1.0
The userspace interface of the kernel crypto API is documented with
* a general explanation
* a discussion of the memory in-place operation
* the description of the message digest API
* the description of the symmetric cipher API
In addition, a fully self contained example that can readily be used as
a library is added as well.
Signed-off-by: Stephan Mueller <[email protected]>
CC: Marek Vasut <[email protected]>
---
Documentation/crypto/crypto-API-userspace.txt | 662 ++++++++++++++++++++++++++
1 file changed, 662 insertions(+)
create mode 100644 Documentation/crypto/crypto-API-userspace.txt
diff --git a/Documentation/crypto/crypto-API-userspace.txt b/Documentation/crypto/crypto-API-userspace.txt
new file mode 100644
index 0000000..30ca6a7
--- /dev/null
+++ b/Documentation/crypto/crypto-API-userspace.txt
@@ -0,0 +1,662 @@
+Introduction
+============
+
+The concepts of the kernel crypto API visible to kernel space is fully
+applicable to the user space interface as well. Therefore, the kernel crypto API
+high level discussion for the in-kernel use cases applies here as well.
+
+The major difference, however, is that user space can only act as a consumer
+and never as a provider of a transformation or cipher algorithm.
+
+The following covers the user space interface exported by the kernel crypto
+API. It provides a fully working sample code at the that can be used as a
+library for user space applications that require cryptographic services from
+the kernel.
+
+Some details of the in-kernel kernel crypto API aspects do not
+apply to user space, however. This includes the difference between synchronous
+and asynchronous invocations. The user space API call is fully synchronous.
+In addition, only a subset of all cipher types are available as documented
+below.
+
+
+User space API general remarks
+==============================
+
+The kernel crypto API is accessible from user space. Currently, the following
+ciphers are accessible:
+
+ * Message digest including keyed message digest (HMAC, CMAC)
+
+ * Symmetric ciphers
+
+Note, AEAD ciphers are currently not supported via the symmetric cipher
+interface.
+
+The interface is provided via Netlink using the type AF_ALG. In addition, the
+setsockopt option type is SOL_ALG. In case the user space header files do not
+export these flags yet, use the following macros:
+
+#ifndef AF_ALG
+#define AF_ALG 38
+#endif
+#ifndef SOL_ALG
+#define SOL_ALG 279
+#endif
+
+A cipher is accessed with the same name as done for the in-kernel API calls.
+This includes the generic vs. unique naming schema for ciphers as well as the
+enforcement of priorities for generic names.
+
+To interact with the kernel crypto API, a Netlink socket must be created by
+the user space application. User space invokes the cipher operation with the
+send/write system call family. The result of the cipher operation is obtained
+with the read/recv system call family.
+
+The following API calls assume that the Netlink socket descriptor is already
+opened by the user space application and discusses only the kernel crypto API
+specific invocations.
+
+In-place cipher operation
+=========================
+
+Just like the in-kernel operation of the kernel crypto API, the user space
+interface allows the cipher operation in-place. That means that the input buffer
+used for the send/write system call and the output buffer used by the read/recv
+system call may be one and the same. This is of particular interest for
+symmetric cipher operations where a copying of the output data to its final
+destination can be avoided.
+
+Message digest API
+==================
+
+The message digest type to be used for the cipher operation is selected when
+invoking the bind syscall. bind requires the caller to provide a filled
+struct sockaddr data structure. This data structure must be filled as follows:
+
+struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "hash", /* this selects the hash logic in the kernel */
+ .salg_name = "sha1" /* this is the cipher name */
+};
+
+The salg_type value "hash" applies to message digests and keyed message digests.
+Though, a keyed message digest is referenced by the appropriate salg_name and
+providing a key for the cipher operation.
+
+Using the send() system call, the application provides the data that should be
+processed with the message digest. The send system call allows the following
+flags to be specified:
+
+ * MSG_MORE: If this flag is set, the send system call acts like a
+ message digest update function where the final hash is not
+ yet calculated. If the flag is not set, the send system call
+ calculates the final message digest immediately.
+
+With the recv() system call, the application can read the message digest from
+the kernel crypto API. If the buffer is too small for the message digest, the
+flag MSG_TRUNC is set by the kernel.
+
+In order to set a message digest key, the calling application must use the
+setsockopt() option of ALG_SET_KEY. If the key is not set the HMAC operation is
+performed without the initial HMAC state change caused by the key.
+
+
+Symmetric cipher API
+====================
+
+The operation is very similar to the message digest discussion. During
+initialization, the struct sockaddr data structure must be filled as follows:
+
+struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "skcipher", /* this selects the symmetric cipher */
+ .salg_name = "cbc(aes)" /* this is the cipher name */
+};
+
+Using the sendmsg() system call, the application provides the data that should
+be processed for encryption or decryption. In addition, the IV is specified
+with the data structure provided by the sendmsg() system call.
+
+The sendmsg system call parameter of struct msghdr is embedded into the
+struct cmsghdr data structure. See recv(2) and cmsg(3) for more information
+on how the cmsghdr data structure is used together with the send/recv system
+call family. That cmsghdr data structure holds the following information
+specified with a separate header instances:
+
+ * specification of the cipher operation type with one of these flags:
+ ALG_OP_ENCRYPT - encryption of data
+ ALG_OP_DECRYPT - decryption of data
+
+ * specification of the IV information marked with the flag ALG_SET_IV
+
+The send system call family allows the following flag to be specified:
+
+ * MSG_MORE: If this flag is set, the send system call acts like a
+ cipher update function where more input data is expected
+ with a subsequent invocation of the send system call.
+
+Note: The kernel reports -EINVAL for any unexpected data. The caller must
+make sure that all data matches the constraints given in /proc/crypto for the
+selected cipher.
+
+With the recv() system call, the application can read the result of the
+cipher operation from the kernel crypto API. The output buffer must be at least
+as large as to hold all blocks of the encrypted or decrypted data. If the output
+data size is smaller, only as many blocks are returned that fit into that
+output buffer size.
+
+User space API example
+======================
+
+Compile the following code with the gcc flags of "-Wextra -Wall -pedantic".
+
+/*
+ * Generic kernel crypto API user space interface library
+ *
+ * Copyright (C) 2014, Stephan Mueller <[email protected]>
+ *
+ * Derived from cryptsetup 1.6.4:
+ *
+ * Linux kernel user space API crypto backend implementation (skcipher)
+ *
+ * Copyright (C) 2012, Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2012, Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * Code from cryptsetup version 1.6.4 used as a basis. See files
+ * lib/crypto_backend/crypto_cipher_kernel.c and
+ * lib/crypto_backend/crypto_kernel.c
+ */
+
+#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;
+ volatile void *_buffer = NULL;
+ unsigned int bufferlen = CMSG_SPACE(sizeof(*type)) + iv_msg_size;
+ struct msghdr msg;
+
+ memset(&msg, 0, sizeof(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);
+ _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]; /* Plaintext */
+#define IVLEN 16
+ unsigned char ivbuf[IVLEN]; /* IV */
+ unsigned char outbuf[BUFLEN]; /* ciphertext for encryption */
+ unsigned char outbuf2[BUFLEN]; /* plaintext for decryption */
+ 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);
+ }
+
+ /* Set key */
+ 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);
+ }
+
+ /* Prepare IV */
+ memcpy(ivbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", IVLEN);
+
+ /*
+ * Encrypt inbuf -- key and plaintext are the same in this example
+ *
+ * It is perfectly legal to use inbuf for the plaintext and ciphertext
+ * pointers. That would mean that after the encryption operation, the
+ * plaintext is overwritten with the cipher text.
+ */
+ if (kcapi_cipher_encrypt(&handle, inbuf, BUFLEN,
+ outbuf, BUFLEN, ivbuf, IVLEN)) {
+ printf("Encryption buffer failed\n");
+ return(1);
+ }
+
+ /* outbuf now contains the cipher text */
+ memset(hexbuf, 0, BUFLEN * 2 + 1);
+ bin2hex(outbuf, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
+ printf("Encrypted data %s\n", hexbuf);
+
+ /*
+ * Decrypt previously encrypted data
+ *
+ * Just like for the encryption operation, the ciphertext buffer pointer
+ * and the plaintext buffer pointer may point to the same memory
+ * location. After completion of this operation, the ciphertext is
+ * overwritten with the plaintext.
+ */
+ 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;
+}
+
+Author
+======
+
+Stephan Mueller <[email protected]>
--
2.1.0
The API function calls exported by the kernel crypto API for AHASHes
to be used by consumers are documented.
Signed-off-by: Stephan Mueller <[email protected]>
CC: Marek Vasut <[email protected]>
---
include/crypto/hash.h | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 224 insertions(+)
diff --git a/include/crypto/hash.h b/include/crypto/hash.h
index 74b13ec..0d43dbc 100644
--- a/include/crypto/hash.h
+++ b/include/crypto/hash.h
@@ -107,11 +107,39 @@ struct crypto_shash {
struct crypto_tfm base;
};
+/**
+ * Asynchronous message digest API to use the ciphers of type
+ * CRYPTO_ALG_TYPE_AHASH (listed as type "ahash" in /proc/crypto)
+ *
+ * The asynchronous cipher operation discussion provided for the
+ * CRYPTO_ALG_TYPE_ABLKCIPHER API applies here as well.
+ *
+ * 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.
+ */
+
static inline struct crypto_ahash *__crypto_ahash_cast(struct crypto_tfm *tfm)
{
return container_of(tfm, struct crypto_ahash, base);
}
+/**
+ * Allocate a cipher handle for an ahash. The returned struct
+ * crypto_ahash is the cipher handle that is required for any subsequent
+ * API invocation for that ahash.
+ *
+ * @alg_name is the cra_name / name or cra_driver_name / driver name of the
+ * ahash cipher
+ * @type specifies the type of the cipher (see Documentation/crypto/)
+ * @mask specifies the mask for the cipher (see Documentation/crypto/)
+ *
+ * return value:
+ * allocated cipher handle in case of success
+ * IS_ERR() is true in case of an error, PTR_ERR() returns the error code.
+ */
struct crypto_ahash *crypto_alloc_ahash(const char *alg_name, u32 type,
u32 mask);
@@ -120,6 +148,11 @@ static inline struct crypto_tfm *crypto_ahash_tfm(struct crypto_ahash *tfm)
return &tfm->base;
}
+/**
+ * The referenced ahash handle is zeroized and subsequently freed.
+ *
+ * @tfm cipher handle to be freed
+ */
static inline void crypto_free_ahash(struct crypto_ahash *tfm)
{
crypto_destroy_tfm(tfm, crypto_ahash_tfm(tfm));
@@ -143,6 +176,15 @@ static inline struct hash_alg_common *crypto_hash_alg_common(
return __crypto_hash_alg_common(crypto_ahash_tfm(tfm)->__crt_alg);
}
+/**
+ * The size for the message digest created by the message digest cipher
+ * referenced with the cipher handle is returned.
+ *
+ * @tfm cipher handle
+ *
+ * return value:
+ * block size of cipher
+ */
static inline unsigned int crypto_ahash_digestsize(struct crypto_ahash *tfm)
{
return crypto_hash_alg_common(tfm)->digestsize;
@@ -168,12 +210,32 @@ static inline void crypto_ahash_clear_flags(struct crypto_ahash *tfm, u32 flags)
crypto_tfm_clear_flags(crypto_ahash_tfm(tfm), flags);
}
+/**
+ * Return the ahash cipher handle that is registered with the asynchronous
+ * request handle ahash_request.
+ *
+ * @req asynchronous request handle that contains the reference to the ahash
+ * cipher handle
+ *
+ * return value:
+ * ahash cipher handle
+ */
static inline struct crypto_ahash *crypto_ahash_reqtfm(
struct ahash_request *req)
{
return __crypto_ahash_cast(req->base.tfm);
}
+/**
+ * Return the size of the ahash state size. With the crypto_ahash_export
+ * function, the caller can export the state into a buffer whose size is
+ * defined with this function.
+ *
+ * @tfm cipher handle
+ *
+ * return value:
+ * size of the ahash state
+ */
static inline unsigned int crypto_ahash_reqsize(struct crypto_ahash *tfm)
{
return tfm->reqsize;
@@ -184,38 +246,159 @@ static inline void *ahash_request_ctx(struct ahash_request *req)
return req->__ctx;
}
+/**
+ * The caller provided key is set for the ahash cipher. The cipher
+ * handle must point to a keyed hash in order for this function to succeed.
+ *
+ * @tfm cipher handle
+ * @key buffer holding the key
+ * @keylen length of the key in bytes
+ *
+ * return value:
+ * 0 if the setting of the key was successful
+ * < 0 if an error occurred
+ */
int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
unsigned int keylen);
+
+/**
+ * This function is a "short-hand" for the function calls of
+ * crypto_ahash_update and crypto_shash_final. The parameters have the same
+ * meaning as discussed for those separate functions.
+ *
+ * return value:
+ * 0 if the message digest creation was successful
+ * < 0 if an error occurred
+ */
int crypto_ahash_finup(struct ahash_request *req);
+
+/**
+ * Finalize the message digest operation and create the message digest
+ * based on all data added to the cipher handle. The message digest is placed
+ * into the output buffer registered with the ahash_request handle.
+ *
+ * @req reference to the ahash_request handle that holds all information
+ * needed to perform the cipher operation
+ *
+ * return value:
+ * 0 if the message digest creation was successful
+ * < 0 if an error occurred
+ */
int crypto_ahash_final(struct ahash_request *req);
+
+/**
+ * This function is a "short-hand" for the function calls of crypto_ahash_init,
+ * crypto_ahash_update and crypto_ahash_final. The parameters have the same
+ * meaning as discussed for those separate three functions.
+ *
+ * return value:
+ * 0 if the message digest creation was successful
+ * < 0 if an error occurred
+ */
int crypto_ahash_digest(struct ahash_request *req);
+/**
+ * This function exports the hash state of the ahash_request handle into the
+ * caller-allocated output buffer out which must have sufficient size (e.g. by
+ * calling crypto_ahash_reqsize).
+ *
+ * @req reference to the ahash_request handle whose state is exported
+ * @out output buffer of sufficient size that can hold the hash state
+ *
+ * return value:
+ * 0 if the export was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_ahash_export(struct ahash_request *req, void *out)
{
return crypto_ahash_reqtfm(req)->export(req, out);
}
+/**
+ * This function imports the hash state into the ahash_request handle from the
+ * input buffer. That buffer should have been generated with the
+ * crypto_ahash_export function.
+ *
+ * @req reference to ahash_request handle the state is imported into
+ * @in buffer holding the state
+ *
+ * return value:
+ * 0 if the import was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_ahash_import(struct ahash_request *req, const void *in)
{
return crypto_ahash_reqtfm(req)->import(req, in);
}
+/**
+ * The call (re-)initializes the message digest referenced by the ahash_request
+ * handle. Any potentially existing state created by previous operations is
+ * discarded.
+ *
+ * @req ahash_request handle that already is initialized with all necessary
+ * data using the ahash_request_* API functions
+ *
+ * return value:
+ * 0 if the message digest initialization was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_ahash_init(struct ahash_request *req)
{
return crypto_ahash_reqtfm(req)->init(req);
}
+/**
+ * Updates the message digest state of the ahash_request handle. The input data
+ * is pointed to by the scatter/gather list registered in the ahash_request
+ * handle
+ *
+ * @req ahash_request handle that was previously initialized with the
+ * crypto_ahash_init call.
+ *
+ * return value:
+ * 0 if the message digest update was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_ahash_update(struct ahash_request *req)
{
return crypto_ahash_reqtfm(req)->update(req);
}
+/**
+ * Allow the caller to replace the existing ahash handle in the request
+ * data structure with a different one.
+ *
+ * @req request handle to be modified
+ * @tfm cipher handle that shall be added to the request handle
+ */
static inline void ahash_request_set_tfm(struct ahash_request *req,
struct crypto_ahash *tfm)
{
req->base.tfm = crypto_ahash_tfm(tfm);
}
+/**
+ * The hash_request data structure contains all pointers to data
+ * required for the asynchronous cipher operation. This includes the cipher
+ * handle (which can be used by multiple ahash_request instances), pointer
+ * to plaintext and the message digest output buffer, asynchronous callback
+ * function, etc. It acts as a handle to the ahash_request_* API calls in a
+ * similar way as ahash handle to the crypto_ahash_* API calls.
+ */
+
+/**
+ * Allocate the request data structure that must be used with the ahash
+ * message digest API calls. During the allocation, the provided ahash handle
+ * is registered in the request data structure.
+ *
+ * @tfm cipher handle to be registered with the request
+ * @gfp memory allocation flag that is handed to kmalloc by the API call.
+ *
+ * return value:
+ * allocated request handle in case of success
+ * IS_ERR() is true in case of an error, PTR_ERR() returns the error code.
+ */
static inline struct ahash_request *ahash_request_alloc(
struct crypto_ahash *tfm, gfp_t gfp)
{
@@ -230,6 +413,11 @@ static inline struct ahash_request *ahash_request_alloc(
return req;
}
+/**
+ * The referenced request data structure is zeroized and subsequently freed.
+ *
+ * @req request data structure cipher handle to be freed
+ */
static inline void ahash_request_free(struct ahash_request *req)
{
kzfree(req);
@@ -241,6 +429,30 @@ static inline struct ahash_request *ahash_request_cast(
return container_of(req, struct ahash_request, base);
}
+/**
+ * Setting the callback function that is triggered once the cipher operation
+ * completes
+ *
+ * The callback function is registered with the ahash_request handle and
+ * must comply with the following template:
+ *
+ * void callback_function(struct crypto_async_request *req, int error)
+ *
+ * @req request handle
+ * @flags specify zero or an ORing 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
+ * @compl callback function pointer to be registered with the request handle
+ * @data 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 data structure provided to the callback function.
+ */
static inline void ahash_request_set_callback(struct ahash_request *req,
u32 flags,
crypto_completion_t compl,
@@ -251,6 +463,18 @@ static inline void ahash_request_set_callback(struct ahash_request *req,
req->base.flags = flags;
}
+/**
+ * By using this call, the caller references the source scatter/gather list.
+ * The source scatter/gather list points to the data the message digest is to
+ * be calculated for.
+ *
+ * @req ahash_request handle to be updated
+ * @src source scatter/gather list
+ * @result buffer that is filled with the message digest -- the caller must
+ * ensure that the buffer has sufficient space by, for example, calling
+ * crypto_ahash_digestsize
+ * @nbytes number of bytes to process from the source scatter/gather list
+ */
static inline void ahash_request_set_crypt(struct ahash_request *req,
struct scatterlist *src, u8 *result,
unsigned int nbytes)
--
2.1.0
The data structure of struct crypto_alg is documented for all parameters
that can be set by a developer of a transformation. All parameters that
are internal to the crypto API are marked as such.
Signed-off-by: Stephan Mueller <[email protected]>
CC: Marek Vasut <[email protected]>
---
include/linux/crypto.h | 157 ++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 137 insertions(+), 20 deletions(-)
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index d45e949..e1a84fd 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -277,22 +277,104 @@ struct rng_alg {
#define cra_compress cra_u.compress
#define cra_rng cra_u.rng
+/**
+ * The struct crypto_alg describes a generic Crypto API algorithm and is common
+ * for all of the transformations. The flags marked as internal shall not
+ * be set or modified by a transformation implementation.
+ */
struct crypto_alg {
- struct list_head cra_list;
- struct list_head cra_users;
-
- u32 cra_flags;
- unsigned int cra_blocksize;
+ struct list_head cra_list; /** <Internal to the Crypto API */
+ struct list_head cra_users; /** <Internal to the Crypto API */
+
+ u32 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.
+ */
+ unsigned int 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.
+ */
unsigned int cra_ctxsize;
- unsigned int cra_alignmask;
-
- int cra_priority;
- atomic_t cra_refcnt;
-
- char cra_name[CRYPTO_MAX_ALG_NAME];
- char cra_driver_name[CRYPTO_MAX_ALG_NAME];
-
- const struct crypto_type *cra_type;
+ unsigned int 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 occasions for different
+ * .cra_u types:
+ * cipher: For both input data and output
+ * data buffer
+ * ahash: For output hash destination buf
+ * shash: For output hash destination buf
+ * This is needed on hardware which is
+ * flawed by design and cannot pick data
+ * from arbitrary addresses.
+ */
+
+ int 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
+ */
+ atomic_t cra_refcnt; /** <Internal to the Crypto API */
+
+ char cra_name[CRYPTO_MAX_ALG_NAME]; /** <Generic name (usable by
+ * multiple implementations) 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.
+ */
+ char cra_driver_name[CRYPTO_MAX_ALG_NAME]; /** <Unique 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.
+ */
+
+ const struct crypto_type *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
+ * crypto_ablkcipher_type
+ * crypto_ahash_type
+ * crypto_aead_type
+ * crypto_rng_type
+ * This field might be empty. In
+ * that case, there are no common
+ * callbacks. This is the case for:
+ * cipher
+ * compress
+ * shash
+ */
union {
struct ablkcipher_alg ablkcipher;
@@ -301,13 +383,48 @@ struct crypto_alg {
struct cipher_alg cipher;
struct compress_alg compress;
struct rng_alg rng;
- } cra_u;
-
- int (*cra_init)(struct crypto_tfm *tfm);
- void (*cra_exit)(struct crypto_tfm *tfm);
- void (*cra_destroy)(struct crypto_alg *alg);
+ } 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.
+ * This field might be empty. This is the case for:
+ * ahash
+ * shash
+ */
+
+ int (*cra_init)(struct crypto_tfm *tfm); /** <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.
+ */
+ void (*cra_exit)(struct crypto_tfm *tfm); /** <Deinitialize the
+ * cryptographic
+ * transformation object.
+ * This is a counterpart to
+ * .cra_init(), used to remove
+ * various changes set in
+ * .cra_init().
+ */
+ void (*cra_destroy)(struct crypto_alg *alg); /** <Internal to the Crypto
+ * API */
- struct module *cra_module;
+ struct module *cra_module; /** <Owner of this transformation
+ * implementation. Set to THIS_MODULE
+ */
};
/*
--
2.1.0
The API function calls exported by the kernel crypto API for AEAD
ciphers to be used by consumers are documented.
Signed-off-by: Stephan Mueller <[email protected]>
CC: Marek Vasut <[email protected]>
---
include/linux/crypto.h | 259 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 259 insertions(+)
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 67acda4..12c8a7a 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -1194,11 +1194,53 @@ static inline void ablkcipher_request_set_crypt(
req->info = iv;
}
+/**
+ * Authenticated Encryption with Associated Data (AEAD) cipher API to use the
+ * ciphers of type CRYPTO_ALG_TYPE_AEAD (listed as type "aead" in /proc/crypto)
+ *
+ * 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))
+ *
+ * The example code provided for the asynchronous block cipher operation
+ * applies here as well. Naturally all *ablkcipher* symbols must be exchanged
+ * the *aead* pendants discussed in the following. In addtion, for the AEAD
+ * operation, the aead_request_set_assoc function must be used to set the
+ * pointer to the associated data memory location before performing the
+ * encryption or decryption operation. In case of an encryption, the associated
+ * data memory is filled during the encryption operation. For decryption, the
+ * associated data memory must contain data that is used to verify the integrity
+ * of the decrypted data. Another deviation from the asynchronous block cipher
+ * operation is that the caller should explicitly check for -EBADMSG of the
+ * crypto_aead_decrypt. That error indicates an authentication error, i.e.
+ * a breach in the integrity of the message. In essence, that -EBADMSG error
+ * code is the key bonus an AEAD cipher has over "standard" block chaining
+ * modes.
+ */
+
static inline struct crypto_aead *__crypto_aead_cast(struct crypto_tfm *tfm)
{
return (struct crypto_aead *)tfm;
}
+/**
+ * Allocate a cipher handle for an AEAD. The returned struct
+ * crypto_aead is the cipher handle that is required for any subsequent
+ * API invocation for that AEAD.
+ *
+ * @alg_name is the cra_name / name or cra_driver_name / driver name of the
+ * AEAD cipher
+ * @type specifies the type of the cipher (see Documentation/crypto/)
+ * @mask specifies the mask for the cipher (see Documentation/crypto/)
+ *
+ * return value:
+ * allocated cipher handle in case of success
+ * IS_ERR() is true in case of an error, PTR_ERR() returns the error code.
+ */
struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask);
static inline struct crypto_tfm *crypto_aead_tfm(struct crypto_aead *tfm)
@@ -1206,6 +1248,11 @@ static inline struct crypto_tfm *crypto_aead_tfm(struct crypto_aead *tfm)
return &tfm->base;
}
+/**
+ * The referenced aead handle is zeroized and subsequently freed.
+ *
+ * @tfm cipher handle to be freed
+ */
static inline void crypto_free_aead(struct crypto_aead *tfm)
{
crypto_free_tfm(crypto_aead_tfm(tfm));
@@ -1216,16 +1263,47 @@ static inline struct aead_tfm *crypto_aead_crt(struct crypto_aead *tfm)
return &crypto_aead_tfm(tfm)->crt_aead;
}
+/**
+ * The size of the IV for the aead referenced by the cipher handle is
+ * returned. This IV size may be zero if the cipher does not need an IV.
+ *
+ * @tfm cipher handle
+ *
+ * return value:
+ * IV size in bytes
+ */
static inline unsigned int crypto_aead_ivsize(struct crypto_aead *tfm)
{
return crypto_aead_crt(tfm)->ivsize;
}
+/**
+ * The maximum size of the authentication data for the AEAD cipher referenced
+ * by the AEAD cipher handle is returned. The authentication data size may be
+ * zero if the cipher implements a hard-coded maximum.
+ *
+ * The authentication data may also be known as "tag value".
+ *
+ * @tfm cipher handle
+ *
+ * return value:
+ * authentication data size / tag size in bytes
+ */
static inline unsigned int crypto_aead_authsize(struct crypto_aead *tfm)
{
return crypto_aead_crt(tfm)->authsize;
}
+/**
+ * The block size for the AEAD referenced with the cipher handle is returned.
+ * The caller may use that information to allocate appropriate memory for the
+ * data returned by the encryption or decryption operation
+ *
+ * @tfm cipher handle
+ *
+ * return value:
+ * block size of cipher
+ */
static inline unsigned int crypto_aead_blocksize(struct crypto_aead *tfm)
{
return crypto_tfm_alg_blocksize(crypto_aead_tfm(tfm));
@@ -1251,6 +1329,23 @@ static inline void crypto_aead_clear_flags(struct crypto_aead *tfm, u32 flags)
crypto_tfm_clear_flags(crypto_aead_tfm(tfm), flags);
}
+/**
+ * The caller provided key is set for the AEAD referenced by the cipher
+ * handle.
+ *
+ * Note, the key length determines the cipher type. Many block ciphers implement
+ * different cipher modes depending on the key size, such as AES-128 vs AES-192
+ * vs. AES-256. When providing a 16 byte key for an AES cipher handle, AES-128
+ * is performed.
+ *
+ * @tfm cipher handle
+ * @key buffer holding the key
+ * @keylen length of the key in bytes
+ *
+ * return value:
+ * 0 if the setting of the key was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_aead_setkey(struct crypto_aead *tfm, const u8 *key,
unsigned int keylen)
{
@@ -1259,6 +1354,17 @@ static inline int crypto_aead_setkey(struct crypto_aead *tfm, const u8 *key,
return crt->setkey(crt->base, key, keylen);
}
+/**
+ * Set the authentication data size / tag size. AEAD requires an authentication
+ * tag (or MAC) in addition to the associated data.
+ *
+ * @tfm cipher handle
+ * @authsize size of the authentication data / tag in bytes
+ *
+ * return value:
+ * 0 if the setting of the key was successful
+ * < 0 if an error occurred
+ */
int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize);
static inline struct crypto_aead *crypto_aead_reqtfm(struct aead_request *req)
@@ -1266,27 +1372,105 @@ static inline struct crypto_aead *crypto_aead_reqtfm(struct aead_request *req)
return __crypto_aead_cast(req->base.tfm);
}
+/**
+ * Encrypt plaintext data using the aead_request handle. That data structure
+ * and how it is filled with data is discussed with the aead_request_*
+ * functions.
+ *
+ * IMPORTANT NOTE: The encryption operation creates the authentication data /
+ * tag. That data is concatenated with the created ciphertext.
+ * The ciphertext memory size is therefore the given number of
+ * block cipher blocks + the size defined by the
+ * crypto_aead_setauthsize invocation. The caller must ensure
+ * that sufficient memory is available for the ciphertext and
+ * the authentication tag.
+ *
+ * @req reference to the aead_request handle that holds all information
+ * needed to perform the cipher operation
+ *
+ * return value:
+ * 0 if the cipher operation was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_aead_encrypt(struct aead_request *req)
{
return crypto_aead_crt(crypto_aead_reqtfm(req))->encrypt(req);
}
+/**
+ * Decrypt ciphertext data using the aead_request handle. That data structure
+ * and how it is filled with data is discussed with the aead_request_*
+ * functions.
+ *
+ * IMPORTANT NOTE: The caller must concatenate the ciphertext followed by the
+ * authentication data / tag. That authentication data / tag
+ * must have the size defined by the crypto_aead_setauthsize
+ * invocation.
+ *
+ * @req reference to the ablkcipher_request handle that holds all information
+ * needed to perform the cipher operation
+ *
+ * return value:
+ * 0 if the cipher operation was successful
+ * -EBADMSG The AEAD cipher operation performs the authentication of the
+ * data during the decryption operation. Therefore, the function
+ * returns this error if the authentication of the ciphertext was
+ * unsuccessful (i.e. the integrity of the ciphertext or the
+ * associated data was violated).
+ * < 0 if an error occurred
+ */
static inline int crypto_aead_decrypt(struct aead_request *req)
{
return crypto_aead_crt(crypto_aead_reqtfm(req))->decrypt(req);
}
+/**
+ * The aead_request data structure contains all pointers to data required for
+ * the AEAD cipher operation. This includes the cipher handle (which can be
+ * used by multiple aead_request instances), pointer to plaintext and
+ * ciphertext, asynchronous callback function, etc. It acts as a handle to the
+ * aead_request_* API calls in a similar way as AEAD handle to the
+ * crypto_aead_* API calls.
+ */
+
+/**
+ * Return the size of the aead_request data structure to the caller.
+ *
+ * @tfm cipher handle
+ *
+ * return value:
+ * number of bytes
+ */
static inline unsigned int crypto_aead_reqsize(struct crypto_aead *tfm)
{
return crypto_aead_crt(tfm)->reqsize;
}
+/**
+ * Allow the caller to replace the existing aead handle in the request
+ * data structure with a different one.
+ *
+ * @req request handle to be modified
+ * @tfm cipher handle that shall be added to the request handle
+ */
static inline void aead_request_set_tfm(struct aead_request *req,
struct crypto_aead *tfm)
{
req->base.tfm = crypto_aead_tfm(crypto_aead_crt(tfm)->base);
}
+/**
+ * Allocate the request data structure that must be used with the AEAD
+ * encrypt and decrypt API calls. During the allocation, the provided aead
+ * handle is registered in the request data structure.
+ *
+ * @tfm cipher handle to be registered with the request
+ * @gfp memory allocation flag that is handed to kmalloc by the API call.
+ *
+ * return value:
+ * allocated request handle in case of success
+ * IS_ERR() is true in case of an error, PTR_ERR() returns the error code.
+ */
static inline struct aead_request *aead_request_alloc(struct crypto_aead *tfm,
gfp_t gfp)
{
@@ -1300,11 +1484,40 @@ static inline struct aead_request *aead_request_alloc(struct crypto_aead *tfm,
return req;
}
+/**
+ * The referenced request data structure is zeroized and subsequently freed.
+ *
+ * @req request data structure cipher handle to be freed
+ */
static inline void aead_request_free(struct aead_request *req)
{
kzfree(req);
}
+/**
+ * Setting the callback function that is triggered once the cipher operation
+ * completes
+ *
+ * The callback function is registered with the aead_request handle and
+ * must comply with the following template:
+ *
+ * void callback_function(struct crypto_async_request *req, int error)
+ *
+ * @req request handle
+ * @flags specify zero or an ORing 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
+ * @compl callback function pointer to be registered with the request handle
+ * @data 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 data structure provided to the callback function.
+ */
static inline void aead_request_set_callback(struct aead_request *req,
u32 flags,
crypto_completion_t compl,
@@ -1315,6 +1528,42 @@ static inline void aead_request_set_callback(struct aead_request *req,
req->base.flags = flags;
}
+/**
+ * Setting the source data and destination data 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.
+ *
+ * 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 illustrates the memory usage:
+ *
+ * //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);
+ *
+ * @req request handle
+ * @src source scatter / gather list
+ * @dst destination scatter / gather list
+ * @cryptlen number of bytes to process from @src
+ * @iv IV for the cipher operation which must comply with the IV size defined
+ * by crypto_aead_ivsize
+ */
static inline void aead_request_set_crypt(struct aead_request *req,
struct scatterlist *src,
struct scatterlist *dst,
@@ -1326,6 +1575,16 @@ static inline void aead_request_set_crypt(struct aead_request *req,
req->iv = iv;
}
+/**
+ * Setting the associated data scatter / gather list.
+ *
+ * For encryption, the memory is filled with the associated data. For
+ * decryption, the memory must point to the associated data.
+ *
+ * @req request handle
+ * @assoc associated data scatter / gather list
+ * @assoclen number of bytes to process from @assoc
+ */
static inline void aead_request_set_assoc(struct aead_request *req,
struct scatterlist *assoc,
unsigned int assoclen)
--
2.1.0
The API function calls exported by the kernel crypto API for
signle block ciphers to be used by consumers are documented.
Signed-off-by: Stephan Mueller <[email protected]>
CC: Marek Vasut <[email protected]>
---
include/linux/crypto.h | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 89 insertions(+)
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index ff15057..b2c3ebb 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -2008,6 +2008,21 @@ static inline void crypto_blkcipher_get_iv(struct crypto_blkcipher *tfm,
memcpy(dst, crypto_blkcipher_crt(tfm)->iv, len);
}
+/**
+ * Single block cipher API to use the ciphers of type CRYPTO_ALG_TYPE_CIPHER
+ * (listed as type "cipher" in /proc/crypto)
+ *
+ * Using the single block cipher API calls, operations with the basic cipher
+ * primitive can be implemented. These cipher primitives exclude any block
+ * chaining operations including IV handling.
+ *
+ * The purpose of this single block cipher API is to support the implementation
+ * of templates or other concepts that only need to perform the cipher operation
+ * on one block at a time. Templates invoke the underlying cipher primitive
+ * block-wise and process either the input or the output data of these cipher
+ * operations.
+ */
+
static inline struct crypto_cipher *__crypto_cipher_cast(struct crypto_tfm *tfm)
{
return (struct crypto_cipher *)tfm;
@@ -2019,6 +2034,20 @@ static inline struct crypto_cipher *crypto_cipher_cast(struct crypto_tfm *tfm)
return __crypto_cipher_cast(tfm);
}
+/**
+ * Allocate a cipher handle for a single block cipher. The returned struct
+ * crypto_cipher is the cipher handle that is required for any subsequent API
+ * invocation for that single block cipher.
+ *
+ * @alg_name is the cra_name / name or cra_driver_name / driver name of the
+ * single block cipher
+ * @type specifies the type of the cipher (see Documentation/crypto/)
+ * @mask specifies the mask for the cipher (see Documentation/crypto/)
+ *
+ * return value:
+ * allocated cipher handle in case of success
+ * IS_ERR() is true in case of an error, PTR_ERR() returns the error code.
+ */
static inline struct crypto_cipher *crypto_alloc_cipher(const char *alg_name,
u32 type, u32 mask)
{
@@ -2034,11 +2063,28 @@ static inline struct crypto_tfm *crypto_cipher_tfm(struct crypto_cipher *tfm)
return &tfm->base;
}
+/**
+ * The referenced single block cipher handle is zeroized and subsequently freed.
+ *
+ * @tfm cipher handle to be freed
+ */
static inline void crypto_free_cipher(struct crypto_cipher *tfm)
{
crypto_free_tfm(crypto_cipher_tfm(tfm));
}
+/**
+ * Lookup function to search for the availability of a given cipher.
+ *
+ * @alg_name is the cra_name / name or cra_driver_name / driver name of the
+ * single block cipher
+ * @type specifies the type of the cipher (see Documentation/crypto/)
+ * @mask specifies the mask for the cipher (see Documentation/crypto/)
+
+ * return value:
+ * true when the single block cipher is known to the kernel crypto API.
+ * false otherwise
+ */
static inline int crypto_has_cipher(const char *alg_name, u32 type, u32 mask)
{
type &= ~CRYPTO_ALG_TYPE_MASK;
@@ -2053,6 +2099,16 @@ static inline struct cipher_tfm *crypto_cipher_crt(struct crypto_cipher *tfm)
return &crypto_cipher_tfm(tfm)->crt_cipher;
}
+/**
+ * The block size for the single block cipher referenced with the cipher handle
+ * tfm is returned. The caller may use that information to allocate appropriate
+ * memory for the data returned by the encryption or decryption operation
+ *
+ * @tfm cipher handle
+ *
+ * return value:
+ * block size of cipher
+ */
static inline unsigned int crypto_cipher_blocksize(struct crypto_cipher *tfm)
{
return crypto_tfm_alg_blocksize(crypto_cipher_tfm(tfm));
@@ -2080,6 +2136,23 @@ static inline void crypto_cipher_clear_flags(struct crypto_cipher *tfm,
crypto_tfm_clear_flags(crypto_cipher_tfm(tfm), flags);
}
+/**
+ * The caller provided key is set for the single block cipher referenced by the
+ * cipher handle.
+ *
+ * Note, the key length determines the cipher type. Many block ciphers implement
+ * different cipher modes depending on the key size, such as AES-128 vs AES-192
+ * vs. AES-256. When providing a 16 byte key for an AES cipher handle, AES-128
+ * is performed.
+ *
+ * @tfm cipher handle
+ * @key buffer holding the key
+ * @keylen length of the key in bytes
+ *
+ * return value:
+ * 0 if the setting of the key was successful
+ * < 0 if an error occurred
+ */
static inline int crypto_cipher_setkey(struct crypto_cipher *tfm,
const u8 *key, unsigned int keylen)
{
@@ -2087,6 +2160,14 @@ static inline int crypto_cipher_setkey(struct crypto_cipher *tfm,
key, keylen);
}
+/**
+ * Invoke the encryption operation of one block. The caller must ensure that
+ * the plaintext and ciphertext buffers are at least one block in size.
+ *
+ * @tfm cipher handle
+ * @dst points to the buffer that will be filled with the ciphertext
+ * @src buffer holding the plaintext to be encrypted
+ */
static inline void crypto_cipher_encrypt_one(struct crypto_cipher *tfm,
u8 *dst, const u8 *src)
{
@@ -2094,6 +2175,14 @@ static inline void crypto_cipher_encrypt_one(struct crypto_cipher *tfm,
dst, src);
}
+/**
+ * Invoke the decryption operation of one block. The caller must ensure that
+ * the plaintext and ciphertext buffers are at least one block in size.
+ *
+ * @tfm cipher handle
+ * @dst points to the buffer that will be filled with the plaintext
+ * @src buffer holding the ciphertext to be decrypted
+ */
static inline void crypto_cipher_decrypt_one(struct crypto_cipher *tfm,
u8 *dst, const u8 *src)
{
--
2.1.0
On Sun, 02 Nov 2014 21:35:11 +0100
Stephan Mueller <[email protected]> wrote:
> The design of the kernel crypto API as well as hints to program with
> the kernel crypto API are given.
Cool to see this, thanks. Please forgive me if I go into full grumpy
editor mode here. There's a lot of good information here, but I think it
could be made better with a bit of effort...
> diff --git a/Documentation/crypto/crypto-API-spec.txt b/Documentation/crypto/crypto-API-spec.txt
> new file mode 100644
> index 0000000..8a24c98
> --- /dev/null
> +++ b/Documentation/crypto/crypto-API-spec.txt
> @@ -0,0 +1,721 @@
> +Kernel Crypto API Interface Specification
> +=========================================
> +
> +The kernel crypto API offers a rich set of cryptographic ciphers as well as
> +other data transformation mechanisms and methods to invoke these. 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 its
> +structure is given. Based on the architecture, the API can be separated into
> +different components. Following the architecture specification, hints to
> +developers of ciphers are provided. Pointers to the API function call
> +documentation are given at the end.
> +
> +The kernel crypto API refers to all algorithms as "transformation". Therefore, a
transformation*s*
> +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.
Should that be s/transforms/transformations/ to keep the terminology
consistent?
> +The kernel crypto API serves the following entity types:
> +
> + * consumers requesting cryptographic services
> +
> + * data transformation implementations (typically ciphers) that
> + can be called by consumers using the kernel crypto API
> +
> +This specification is intended for consumers of the kernel crypto API as well
> +as for developers implementing ciphers. This API specification, however, does
> +not discusses 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).
> +
> +Note: The terms "transformation" and cipher algorithm are used interchangably.
> +
> +
> +Terminology
> +-----------
> +
> +The transformation implementation is an actual code or interface to hardware
> +which implements a certain transformation with precisely 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 or another transformation. 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).
It seems like it would be good to show what this object is and how to
allocate it here, rather than just teasing the reader saying it's possible?
> +The transformation context is private data associated with the transformation
> +object.
> +
> +
> +Kernel Crypto API Architecture
> +==============================
> +
> +Cipher algorithm 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 single block ciphers and
> +message digests. In addition, the kernel crypto API provides numerous
> +"templates" that can be used in conjunction with the single block ciphers and
> +message digests. Templates include all types of block chaining mode, the HMAC
> +mechanism, etc.
> +
> +Single block ciphers and message digests can either be directly used by a
> +caller or invoked together with a template to form multi-block ciphers or keyed
> +message digests.
> +
> +A single block cipher may even be called with multiple templates. However,
> +templates cannot be used without a single cipher.
> +
> +
> +Synchronous and asynchronous operation
> +--------------------------------------
> +
> +The kernel crypto API provides synchronous and asynchronous API operations.
> +
> +When using the synchronous API operation, 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 operation, the set
> +of API calls is small and conceptually 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(single block cipher)
> +
> +where "template" and "single block cipher" is the aforementioned template and
> +single block cipher, respectively. If applicable, additional templates may
> +enclose other templates, such as
> +
> + template1(template2(single block cipher)))
I suspect a lot of readers may reach the glaze-over point around here. The
discussion is useful but all very abstract and hard to tie to the actual
crypto code. A real-world example here would help.
> +The kernel crypto API may provide multiple implementations of a template or a
> +single block cipher. For example, AES on newer Intel 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.
This seems like detail stuff that should go with the actual API description?
> +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 are listed. However, that list does not specify all
Those two sentences repeat each other. Anyway, that's available ciphers in
a running kernel, presumably, and not everything that could be build into a
kernel. A useful distinction to make.
> +possible permutations of templates and ciphers. 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
So, it's not just a name, it's a qualified name - "ctr(aes)" rather than
just "aes". How is the reader to interpret that extra information?
> + * 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 consumers 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 single block ciphers that may be used with an
> + additional template
> + - 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
Worth saying that some of these fields won't be present if they are not
relevant?
> + * 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
> + and handling as it is specific to the given cipher
> +
> +
> +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-192 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 Raw block cipher
> + * CRYPTO_ALG_TYPE_COMPRESS Compression
> + * CRYPTO_ALG_TYPE_AEAD Authenticated Encryption with Associated Data (MAC)
> + * CRYPTO_ALG_TYPE_BLKCIPHER Synchronous multi-block cipher
> + * CRYPTO_ALG_TYPE_ABLKCIPHER Asynchronous multi-block cipher
> + * CRYPTO_ALG_TYPE_GIVCIPHER
What's this one?
> + * CRYPTO_ALG_TYPE_DIGEST Raw message digest
> + * CRYPTO_ALG_TYPE_HASH Alias for CRYPTO_ALG_TYPE_DIGEST
> + * CRYPTO_ALG_TYPE_SHASH Synchronous multi-block hash
> + * CRYPTO_ALG_TYPE_AHASH Asynchronous multi-block hash
> + * CRYPTO_ALG_TYPE_RNG Random Number Generation
> + * CRYPTO_ALG_TYPE_PCOMPRESS
What's that last one?
> +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.
> +
> +When the caller provides a mask and type specification, the caller limits the
> +kernel crypto API´s search for a suitable cipher implementation for the given
> +cipher name. That means, even when a caller uses a cipher name that exists
> +during its initialization call, the kernel crypto API may not select it due
> +to the used type and mask field.
> +
> +
> +Developing Cipher Algorithms
> +============================
> +
> +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);
> +
This would be a good place to talk about struct crypto_alg?
> +Notice that both registration and unregistration functions do return a value,
> +so make sure to handle errors.
What is the form of the error return?
> +The bulk registration / unregistration functions require that struct crypto_alg
> +is an array of count size. These functions simply loop over that array and
> +register / unregister each individual algorithm. If an error occurs, the
> +loop is terminated at the offending algorithm definition. That means, the
> +algorithms prior to the offending algorithm are successfully registered.
What is the return value in the error case? How does the caller determine
which one failed?
> +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.
> +
> +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.
You haven't really introduced this structure, though, so the reader doesn't
really know what fields exist and which should be worried about.
> +Fields in struct cipher_alg explained
> +.....................................
And struct cipher_alg is totally new and could use some introduction.
Where is it used?
> +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.
What's this software fallback and cra_init() of which you speak? Most
readers will have no clue of what you're talking about here.
> + .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.
This is about where I realize life might be better if you gave full
function prototypes. Where is cra_blocksize specified?
> + - 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
> +
> +
> +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.
> +
> +Registration specifics
> +......................
> +
> +The registration of [BLKCIPHER] or [ABLKCIPHER] algorithms 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()
But just above you said that the crypto subsystem would copy data to align
it if need be?
> +or crypto_ablkcipher_alignmask() respectively to determine the needs of the
> +transformation object and prepare the scatterlist with data accordingly.
> +
> +Fields in struct blkcipher_alg and struct ablkcipher_alg explained
> +..................................................................
Where are these structs used?
> +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 the single block cipher description for schematics of the block
> +cipher usage. The usage patterns are exactly the same for [ABLKCIPHER] and
> +[BLKCIPHER] as they are for plain [CIPHER].
> +
> +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
> +below for a 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.
What's a generic crypto queue? That's a new concept.
> +Hashing [HASH]
> +--------------
> +
> +Example of transformations: crc32, md5, sha1, sha256,...
> +
> +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
s/amount/number/
> +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);
Yay, full prototypes. But can we introduce that structure too? I guess
you sort-of do that below.
> +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);
> +
> +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.
Push *a* chunk...
> + - 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,
What does "finalize" mean in this context?
> + 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.
Are functions like these mandatory, or will the crypto core call the
sequence separately if need be?
> + .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
> +
> +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:
Where is this structure used?
> + 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.
> +
> +
> +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.
> +
> +
> +Single block cipher API
> +=======================
> +
> +See source code comments for the *_cipher* calls in include/linux/crypto.h.
> +
> +
> +Synchronous block cipher API
> +============================
> +
> +See source code comments for the *_blkcipher* calls in include/linux/crypto.h.
> +
> +
> +Asynchronous block cipher API
> +=============================
> +
> +See source code comments for the *_ablkcipher* calls and "ablkcipher_request_*
> +calls in include/linux/crypto.h.
> +
> +
> +Synchronous message digest API
> +==============================
> +
> +See source code comments for the *_hash* calls in include/linux/crypto.h.
> +
> +
> +Synchronous message digest API with caller-accessible state space
> +=================================================================
> +
> +See source code comments for the *_shash* calls in include/crypto/hash.h.
> +
> +
> +Asynchronous message digest API
> +===============================
> +
> +See source code comments for the *_ahash* calls and "ahash_request_*
> +calls in include/crypto/hash.h.
> +
> +
> +Random number generation API
> +============================
> +
> +See source code comments for the *_rng* calls in include/crypto/hash.h.
> +
> +
> +AEAD asynchronous cipher API
> +============================
> +
> +See source code comments for the *_aead* calls and "aead_request_*
> +calls in include/linux/crypto.h.
These are all useful. But I wonder if it would be worth the effort to turn
this inti a proper docbook document that automatically has everything
together in one place?
> +
> +Authors
> +=======
> +
> +Stephan Mueller <[email protected]>
> +Marek Vasut <[email protected]>
jon
Am Montag, 3. November 2014, 08:34:39 schrieb Jonathan Corbet:
Hi Jonathan,
> On Sun, 02 Nov 2014 21:35:11 +0100
>
> Stephan Mueller <[email protected]> wrote:
> > The design of the kernel crypto API as well as hints to program with
> > the kernel crypto API are given.
>
> Cool to see this, thanks. Please forgive me if I go into full grumpy
> editor mode here. There's a lot of good information here, but I think it
> could be made better with a bit of effort...
Thanks for your comments.
I will include your suggestions into a new patch set. Once you staring at that
documentation for too long, you will not find errors any more :-)
[...]
> > +
> > + * CRYPTO_ALG_TYPE_CIPHER Raw block cipher
> > + * CRYPTO_ALG_TYPE_COMPRESS Compression
> > + * CRYPTO_ALG_TYPE_AEAD Authenticated Encryption with
Associated Data
> > (MAC) + * CRYPTO_ALG_TYPE_BLKCIPHER Synchronous multi-block cipher
> > + * CRYPTO_ALG_TYPE_ABLKCIPHER Asynchronous multi-block cipher
> > + * CRYPTO_ALG_TYPE_GIVCIPHER
>
> What's this one?
I would like to ask Herbert what that is -- I looked around in the code and I
am not sure what that flag shall indicate.
>
> > + * CRYPTO_ALG_TYPE_DIGEST Raw message digest
> > + * CRYPTO_ALG_TYPE_HASH Alias for CRYPTO_ALG_TYPE_DIGEST
> > + * CRYPTO_ALG_TYPE_SHASH Synchronous multi-block hash
> > + * CRYPTO_ALG_TYPE_AHASH Asynchronous multi-block hash
> > + * CRYPTO_ALG_TYPE_RNG Random Number Generation
> > + * CRYPTO_ALG_TYPE_PCOMPRESS
>
> What's that last one?
Same here.
[...]
> > +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
> > +below for a 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.
>
> What's a generic crypto queue? That's a new concept.
Right. I do not claim to have all completed right from the start. If so, there
is much more: the AEAD and RNG implementation details are missing here too.
Therefore, I thought I could leave it open for the moment to add in later.
[..]
>
> These are all useful. But I wonder if it would be worth the effort to turn
> this inti a proper docbook document that automatically has everything
> together in one place?
How do you suggest that is done? The API comments in the header file follow
the Doxygen style. Note, Jason Cooper raised the concern that an API
documentation separate from the code will surely deviate from the code
relatively fast (although I do not really fear that as the kernel crypto API
seems to be quite stable over the last years).
Can you point me to an example about what you have in mind? I see the
Documentation/DocBook/ files, but I do not see how they integrate Doxygen-like
source code comments added to functions.
>
> > +
> > +Authors
> > +=======
> > +
> > +Stephan Mueller <[email protected]>
> > +Marek Vasut <[email protected]>
>
> jon
--
Ciao
Stephan
On Mon, Nov 03, 2014 at 03:18:29PM +0100, Stephan Mueller wrote:
>
> > > + * CRYPTO_ALG_TYPE_CIPHER Raw block cipher
> > > + * CRYPTO_ALG_TYPE_COMPRESS Compression
> > > + * CRYPTO_ALG_TYPE_AEAD Authenticated Encryption with
> Associated Data
> > > (MAC) + * CRYPTO_ALG_TYPE_BLKCIPHER Synchronous multi-block cipher
> > > + * CRYPTO_ALG_TYPE_ABLKCIPHER Asynchronous multi-block cipher
> > > + * CRYPTO_ALG_TYPE_GIVCIPHER
> >
> > What's this one?
>
> I would like to ask Herbert what that is -- I looked around in the code and I
> am not sure what that flag shall indicate.
givcipher is an ablkcipher packed together with an IV generator.
Cheers,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
On Mon, Nov 03, 2014 at 03:18:29PM +0100, Stephan Mueller wrote:
>
> > > + * CRYPTO_ALG_TYPE_DIGEST Raw message digest
> > > + * CRYPTO_ALG_TYPE_HASH Alias for CRYPTO_ALG_TYPE_DIGEST
> > > + * CRYPTO_ALG_TYPE_SHASH Synchronous multi-block hash
> > > + * CRYPTO_ALG_TYPE_AHASH Asynchronous multi-block hash
> > > + * CRYPTO_ALG_TYPE_RNG Random Number Generation
> > > + * CRYPTO_ALG_TYPE_PCOMPRESS
> >
> > What's that last one?
>
> Same here.
pcompress is an enhanced version of compress allowing for piece-meal
compression/decompression rather than having to shove everything in
all at once.
Eventually pcompress should replace the compress interface once
everything is converted across.
Thanks,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
On 11/03/2014 08:49 AM, Herbert Xu wrote:
> On Mon, Nov 03, 2014 at 03:18:29PM +0100, Stephan Mueller wrote:
>>
>>>> + * CRYPTO_ALG_TYPE_DIGEST Raw message digest
>>>> + * CRYPTO_ALG_TYPE_HASH Alias for CRYPTO_ALG_TYPE_DIGEST
>>>> + * CRYPTO_ALG_TYPE_SHASH Synchronous multi-block hash
>>>> + * CRYPTO_ALG_TYPE_AHASH Asynchronous multi-block hash
>>>> + * CRYPTO_ALG_TYPE_RNG Random Number Generation
>>>> + * CRYPTO_ALG_TYPE_PCOMPRESS
>>>
>>> What's that last one?
>>
>> Same here.
>
> pcompress is an enhanced version of compress allowing for piece-meal
> compression/decompression rather than having to shove everything in
> all at once.
>
> Eventually pcompress should replace the compress interface once
> everything is converted across.
Herbert, I was looking at adding async support for ALG_TYPE_COMPRESS
since the CCP device will support compression/decompression but only
as an everything at once invocation. Given what you're saying about
pcompress replacing compress, would this be something you'd even
consider though?
Thanks,
Tom
>
> Thanks,
>
On Mon, 03 Nov 2014 15:18:29 +0100
Stephan Mueller <[email protected]> wrote:
> > These are all useful. But I wonder if it would be worth the effort to turn
> > this inti a proper docbook document that automatically has everything
> > together in one place?
>
> How do you suggest that is done?
See Documentation/kernel-doc-nano-HOWTO.txt for an introduction to the
process. This documentation hasn't seen a lot of maintenance recently,
but I don't think things have changed too much. Should check that when I
get a chance...
Thanks,
jon
Hi Stephan,
Great docs! I think they will be very useful! Thanks!
I only have 2 comments below.
regards,
Joy
On Sun, 2014-11-02 at 21:35 +0100, Stephan Mueller wrote:
> The design of the kernel crypto API as well as hints to program with
> the kernel crypto API are given.
>
> The documentation contains:
> * design aspects of crypto API
> * develper specific hints
> * references to the API function description
>
> Signed-off-by: Stephan Mueller <[email protected]>
> CC: Marek Vasut <[email protected]>
> ---
> Documentation/crypto/crypto-API-spec.txt | 721 +++++++++++++++++++++++++++++++
> 1 file changed, 721 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..8a24c98
> --- /dev/null
> +++ b/Documentation/crypto/crypto-API-spec.txt
> @@ -0,0 +1,721 @@
> +Kernel Crypto API Interface Specification
> +=========================================
> +
> +The kernel crypto API offers a rich set of cryptographic ciphers as well as
> +other data transformation mechanisms and methods to invoke these. 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 its
> +structure is given. Based on the architecture, the API can be separated into
> +different components. Following the architecture specification, hints to
> +developers of ciphers are provided. Pointers to the API function call
> +documentation are given at the end.
> +
> +The kernel crypto API refers to all algorithms as "transformation". 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:
> +
> + * consumers requesting cryptographic services
> +
> + * data transformation implementations (typically ciphers) that
> + can be called by consumers using the kernel crypto API
> +
> +This specification is intended for consumers of the kernel crypto API as well
> +as for developers implementing ciphers. This API specification, however, does
> +not discusses 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).
> +
> +Note: The terms "transformation" and cipher algorithm are used interchangably.
> +
> +
> +Terminology
> +-----------
> +
> +The transformation implementation is an actual code or interface to hardware
> +which implements a certain transformation with precisely 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 or another transformation. 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.
> +
> +
> +Kernel Crypto API Architecture
> +==============================
> +
> +Cipher algorithm 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 single block ciphers and
> +message digests. In addition, the kernel crypto API provides numerous
> +"templates" that can be used in conjunction with the single block ciphers and
> +message digests. Templates include all types of block chaining mode, the HMAC
> +mechanism, etc.
> +
> +Single block ciphers and message digests can either be directly used by a
> +caller or invoked together with a template to form multi-block ciphers or keyed
> +message digests.
> +
> +A single block cipher may even be called with multiple templates. However,
> +templates cannot be used without a single cipher.
Although you go into further explanation shortly, I think an example or
two here might help reader to immediately grab concept. i.e. aes,
cbc(aes), ...
> +
> +
> +Synchronous and asynchronous operation
> +--------------------------------------
> +
> +The kernel crypto API provides synchronous and asynchronous API operations.
> +
> +When using the synchronous API operation, 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 operation, the set
> +of API calls is small and conceptually 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(single block cipher)
> +
> +where "template" and "single block cipher" is the aforementioned template and
> +single block cipher, respectively. If applicable, additional templates may
> +enclose other templates, such as
> +
> + template1(template2(single block cipher)))
> +
> +The kernel crypto API may provide multiple implementations of a template or a
> +single block cipher. For example, AES on newer Intel 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 are listed. However, that list does not specify all
> +possible permutations of templates and ciphers. 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 consumers 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 single block ciphers that may be used with an
> + additional template
> + - 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
> + and handling as it is specific to the given cipher
> +
> +
> +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-192 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 Raw block cipher
> + * CRYPTO_ALG_TYPE_COMPRESS Compression
> + * CRYPTO_ALG_TYPE_AEAD Authenticated Encryption with Associated Data (MAC)
> + * CRYPTO_ALG_TYPE_BLKCIPHER Synchronous multi-block cipher
> + * CRYPTO_ALG_TYPE_ABLKCIPHER Asynchronous multi-block cipher
> + * CRYPTO_ALG_TYPE_GIVCIPHER
> + * CRYPTO_ALG_TYPE_DIGEST Raw message digest
> + * CRYPTO_ALG_TYPE_HASH Alias for CRYPTO_ALG_TYPE_DIGEST
> + * CRYPTO_ALG_TYPE_SHASH Synchronous multi-block hash
> + * CRYPTO_ALG_TYPE_AHASH Asynchronous multi-block hash
> + * CRYPTO_ALG_TYPE_RNG Random Number Generation
> + * 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.
> +
> +When the caller provides a mask and type specification, the caller limits the
> +kernel crypto API´s search for a suitable cipher implementation for the given
> +cipher name. That means, even when a caller uses a cipher name that exists
> +during its initialization call, the kernel crypto API may not select it due
> +to the used type and mask field.
> +
> +
> +Developing Cipher Algorithms
> +============================
> +
> +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.
> +
> +The bulk registration / unregistration functions require that struct crypto_alg
> +is an array of count size. These functions simply loop over that array and
> +register / unregister each individual algorithm. If an error occurs, the
> +loop is terminated at the offending algorithm definition. That means, the
> +algorithms prior to the offending algorithm are successfully registered.
> +
> +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.
> +
Picky, but I think maybe transitioning reader to the symmetric ciphers
might be a bit helpful here... because I was still interpreting "cipher"
as meaning everything. But after scanning below I think we are only
talking about symmetric ciphers now...
> +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.
> +
> +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
> +
> +
> +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.
> +
> +Registration specifics
> +......................
> +
> +The registration of [BLKCIPHER] or [ABLKCIPHER] algorithms 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.
> +
> +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 the single block cipher description for schematics of the block
> +cipher usage. The usage patterns are exactly the same for [ABLKCIPHER] and
> +[BLKCIPHER] as they are for plain [CIPHER].
> +
> +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
> +below for a 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.
> +
> +
> +Hashing [HASH]
> +--------------
> +
> +Example of transformations: crc32, md5, sha1, sha256,...
> +
> +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);
> +
> +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.
> +
Maybe it would be good to mention that setkey is only required for
"keyed message digests" such as the hmacs. Although you do point this
out above by naming them.
> - 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
> +
> +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.
> +
> +
> +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.
> +
> +
> +Single block cipher API
> +=======================
> +
> +See source code comments for the *_cipher* calls in include/linux/crypto.h.
> +
> +
> +Synchronous block cipher API
> +============================
> +
> +See source code comments for the *_blkcipher* calls in include/linux/crypto.h.
> +
> +
> +Asynchronous block cipher API
> +=============================
> +
> +See source code comments for the *_ablkcipher* calls and "ablkcipher_request_*
> +calls in include/linux/crypto.h.
> +
> +
> +Synchronous message digest API
> +==============================
> +
> +See source code comments for the *_hash* calls in include/linux/crypto.h.
> +
> +
> +Synchronous message digest API with caller-accessible state space
> +=================================================================
> +
> +See source code comments for the *_shash* calls in include/crypto/hash.h.
> +
> +
> +Asynchronous message digest API
> +===============================
> +
> +See source code comments for the *_ahash* calls and "ahash_request_*
> +calls in include/crypto/hash.h.
> +
> +
> +Random number generation API
> +============================
> +
> +See source code comments for the *_rng* calls in include/crypto/hash.h.
> +
> +
> +AEAD asynchronous cipher API
> +============================
> +
> +See source code comments for the *_aead* calls and "aead_request_*
> +calls in include/linux/crypto.h.
> +
> +
> +Authors
> +=======
> +
> +Stephan Mueller <[email protected]>
> +Marek Vasut <[email protected]>
Hi Stephan,
On Sun, 2014-11-02 at 21:36 +0100, Stephan Mueller wrote:
> The userspace interface of the kernel crypto API is documented with
> * a general explanation
> * a discussion of the memory in-place operation
> * the description of the message digest API
> * the description of the symmetric cipher API
>
> In addition, a fully self contained example that can readily be used as
> a library is added as well.
>
> Signed-off-by: Stephan Mueller <[email protected]>
> CC: Marek Vasut <[email protected]>
> ---
> Documentation/crypto/crypto-API-userspace.txt | 662 ++++++++++++++++++++++++++
> 1 file changed, 662 insertions(+)
> create mode 100644 Documentation/crypto/crypto-API-userspace.txt
>
> diff --git a/Documentation/crypto/crypto-API-userspace.txt b/Documentation/crypto/crypto-API-userspace.txt
> new file mode 100644
> index 0000000..30ca6a7
> --- /dev/null
> +++ b/Documentation/crypto/crypto-API-userspace.txt
> @@ -0,0 +1,662 @@
> +Introduction
> +============
> +
> +The concepts of the kernel crypto API visible to kernel space is fully
> +applicable to the user space interface as well. Therefore, the kernel crypto API
> +high level discussion for the in-kernel use cases applies here as well.
> +
> +The major difference, however, is that user space can only act as a consumer
> +and never as a provider of a transformation or cipher algorithm.
> +
> +The following covers the user space interface exported by the kernel crypto
> +API. It provides a fully working sample code at the that can be used as a
"at the" can probably be deleted.
> +library for user space applications that require cryptographic services from
> +the kernel.
> +
> +Some details of the in-kernel kernel crypto API aspects do not
> +apply to user space, however. This includes the difference between synchronous
> +and asynchronous invocations. The user space API call is fully synchronous.
> +In addition, only a subset of all cipher types are available as documented
> +below.
> +
> +
> +User space API general remarks
> +==============================
> +
> +The kernel crypto API is accessible from user space. Currently, the following
> +ciphers are accessible:
> +
> + * Message digest including keyed message digest (HMAC, CMAC)
> +
> + * Symmetric ciphers
> +
> +Note, AEAD ciphers are currently not supported via the symmetric cipher
> +interface.
> +
> +The interface is provided via Netlink using the type AF_ALG. In addition, the
> +setsockopt option type is SOL_ALG. In case the user space header files do not
> +export these flags yet, use the following macros:
> +
> +#ifndef AF_ALG
> +#define AF_ALG 38
> +#endif
> +#ifndef SOL_ALG
> +#define SOL_ALG 279
> +#endif
> +
> +A cipher is accessed with the same name as done for the in-kernel API calls.
> +This includes the generic vs. unique naming schema for ciphers as well as the
> +enforcement of priorities for generic names.
> +
> +To interact with the kernel crypto API, a Netlink socket must be created by
> +the user space application. User space invokes the cipher operation with the
> +send/write system call family. The result of the cipher operation is obtained
> +with the read/recv system call family.
> +
> +The following API calls assume that the Netlink socket descriptor is already
> +opened by the user space application and discusses only the kernel crypto API
> +specific invocations.
> +
> +In-place cipher operation
> +=========================
> +
> +Just like the in-kernel operation of the kernel crypto API, the user space
> +interface allows the cipher operation in-place. That means that the input buffer
> +used for the send/write system call and the output buffer used by the read/recv
> +system call may be one and the same. This is of particular interest for
> +symmetric cipher operations where a copying of the output data to its final
> +destination can be avoided.
For clarity, it might be helpful to reader if both ways are mentioned.
That you can encrypt in place or have your output place in a separate
destination.
> +
> +Message digest API
> +==================
> +
> +The message digest type to be used for the cipher operation is selected when
> +invoking the bind syscall. bind requires the caller to provide a filled
> +struct sockaddr data structure. This data structure must be filled as follows:
> +
> +struct sockaddr_alg sa = {
> + .salg_family = AF_ALG,
> + .salg_type = "hash", /* this selects the hash logic in the kernel */
> + .salg_name = "sha1" /* this is the cipher name */
> +};
> +
> +The salg_type value "hash" applies to message digests and keyed message digests.
> +Though, a keyed message digest is referenced by the appropriate salg_name and
> +providing a key for the cipher operation.
Picky, but maybe now is the time to mention what you mention 2 or 3
paragraphs below about how to set the message digest key.
> +
> +Using the send() system call, the application provides the data that should be
> +processed with the message digest. The send system call allows the following
> +flags to be specified:
> +
> + * MSG_MORE: If this flag is set, the send system call acts like a
> + message digest update function where the final hash is not
> + yet calculated. If the flag is not set, the send system call
> + calculates the final message digest immediately.
> +
> +With the recv() system call, the application can read the message digest from
> +the kernel crypto API. If the buffer is too small for the message digest, the
> +flag MSG_TRUNC is set by the kernel.
> +
> +In order to set a message digest key, the calling application must use the
> +setsockopt() option of ALG_SET_KEY. If the key is not set the HMAC operation is
> +performed without the initial HMAC state change caused by the key.
> +
> +
> +Symmetric cipher API
> +====================
> +
> +The operation is very similar to the message digest discussion. During
> +initialization, the struct sockaddr data structure must be filled as follows:
> +
> +struct sockaddr_alg sa = {
> + .salg_family = AF_ALG,
> + .salg_type = "skcipher", /* this selects the symmetric cipher */
> + .salg_name = "cbc(aes)" /* this is the cipher name */
> +};
> +
> +Using the sendmsg() system call, the application provides the data that should
> +be processed for encryption or decryption. In addition, the IV is specified
> +with the data structure provided by the sendmsg() system call.
> +
> +The sendmsg system call parameter of struct msghdr is embedded into the
> +struct cmsghdr data structure. See recv(2) and cmsg(3) for more information
> +on how the cmsghdr data structure is used together with the send/recv system
> +call family. That cmsghdr data structure holds the following information
> +specified with a separate header instances:
> +
> + * specification of the cipher operation type with one of these flags:
> + ALG_OP_ENCRYPT - encryption of data
> + ALG_OP_DECRYPT - decryption of data
> +
> + * specification of the IV information marked with the flag ALG_SET_IV
> +
> +The send system call family allows the following flag to be specified:
> +
> + * MSG_MORE: If this flag is set, the send system call acts like a
> + cipher update function where more input data is expected
> + with a subsequent invocation of the send system call.
> +
> +Note: The kernel reports -EINVAL for any unexpected data. The caller must
> +make sure that all data matches the constraints given in /proc/crypto for the
> +selected cipher.
> +
> +With the recv() system call, the application can read the result of the
> +cipher operation from the kernel crypto API. The output buffer must be at least
> +as large as to hold all blocks of the encrypted or decrypted data. If the output
> +data size is smaller, only as many blocks are returned that fit into that
> +output buffer size.
> +
> +User space API example
> +======================
> +
> +Compile the following code with the gcc flags of "-Wextra -Wall -pedantic".
> +
> +/*
> + * Generic kernel crypto API user space interface library
> + *
> + * Copyright (C) 2014, Stephan Mueller <[email protected]>
> + *
> + * Derived from cryptsetup 1.6.4:
> + *
> + * Linux kernel user space API crypto backend implementation (skcipher)
> + *
> + * Copyright (C) 2012, Red Hat, Inc. All rights reserved.
> + * Copyright (C) 2012, Milan Broz
> + *
> + * This file is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This file is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this file; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +/*
> + * Code from cryptsetup version 1.6.4 used as a basis. See files
> + * lib/crypto_backend/crypto_cipher_kernel.c and
> + * lib/crypto_backend/crypto_kernel.c
> + */
> +
> +#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;
> + volatile void *_buffer = NULL;
> + unsigned int bufferlen = CMSG_SPACE(sizeof(*type)) + iv_msg_size;
> + struct msghdr msg;
> +
> + memset(&msg, 0, sizeof(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);
> + _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]; /* Plaintext */
> +#define IVLEN 16
> + unsigned char ivbuf[IVLEN]; /* IV */
> + unsigned char outbuf[BUFLEN]; /* ciphertext for encryption */
> + unsigned char outbuf2[BUFLEN]; /* plaintext for decryption */
> + 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);
> + }
> +
> + /* Set key */
> + 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);
> + }
> +
> + /* Prepare IV */
> + memcpy(ivbuf, "\x00\x01\x02\x03\x04\x05\x06\x07"
> + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", IVLEN);
> +
> + /*
> + * Encrypt inbuf -- key and plaintext are the same in this example
> + *
> + * It is perfectly legal to use inbuf for the plaintext and ciphertext
> + * pointers. That would mean that after the encryption operation, the
> + * plaintext is overwritten with the cipher text.
> + */
> + if (kcapi_cipher_encrypt(&handle, inbuf, BUFLEN,
> + outbuf, BUFLEN, ivbuf, IVLEN)) {
> + printf("Encryption buffer failed\n");
> + return(1);
> + }
> +
> + /* outbuf now contains the cipher text */
> + memset(hexbuf, 0, BUFLEN * 2 + 1);
> + bin2hex(outbuf, BUFLEN, hexbuf, BUFLEN * 2 + 1, 0);
> + printf("Encrypted data %s\n", hexbuf);
> +
> + /*
> + * Decrypt previously encrypted data
> + *
> + * Just like for the encryption operation, the ciphertext buffer pointer
> + * and the plaintext buffer pointer may point to the same memory
> + * location. After completion of this operation, the ciphertext is
> + * overwritten with the plaintext.
> + */
> + 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;
> +}
> +
> +Author
> +======
> +
> +Stephan Mueller <[email protected]>
regards,
Joy
Hi Stephan,
Just one quick comment below...
regards,
Joy
On Sun, 2014-11-02 at 21:36 +0100, Stephan Mueller wrote:
> The API function calls exported by the kernel crypto API for RNGs to
> be used by consumers are documented.
>
> Signed-off-by: Stephan Mueller <[email protected]>
> CC: Marek Vasut <[email protected]>
> ---
> include/crypto/rng.h | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 113 insertions(+)
>
> diff --git a/include/crypto/rng.h b/include/crypto/rng.h
> index c93f9b9..83c4238 100644
> --- a/include/crypto/rng.h
> +++ b/include/crypto/rng.h
> @@ -20,11 +20,68 @@ extern struct crypto_rng *crypto_default_rng;
> int crypto_get_default_rng(void);
> void crypto_put_default_rng(void);
>
> +/**
> + * Random number generator API to use the ciphers of type
> + * CRYPTO_ALG_TYPE_RNG (listed as type "rng" in /proc/crypto)
> + *
> + * 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;
> + *}
> + */
> +
> static inline struct crypto_rng *__crypto_rng_cast(struct crypto_tfm *tfm)
> {
> return (struct crypto_rng *)tfm;
> }
>
> +/**
> + * Allocate a cipher handle for a random number generator. The returned struct
> + * crypto_rng is the cipher handle that is required for any subsequent
> + * API invocation for 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 cra_name / name or cra_driver_name / driver name of the
> + * message digest cipher
> + * @type specifies the type of the cipher (see Documentation/crypto/)
> + * @mask specifies the mask for the cipher (see Documentation/crypto/)
> + *
> + * return value:
> + * allocated cipher handle in case of success
> + * IS_ERR() is true in case of an error, PTR_ERR() returns the error code.
> + */
> static inline struct crypto_rng *crypto_alloc_rng(const char *alg_name,
> u32 type, u32 mask)
> {
> @@ -40,6 +97,14 @@ static inline struct crypto_tfm *crypto_rng_tfm(struct crypto_rng *tfm)
> return &tfm->base;
> }
>
> +/**
> + * Return the generic name (cra_name) of the initialized random number generator
> + *
> + * @tfm cipher handle
> + *
> + * return value:
> + * generic name string
> + */
> static inline struct rng_alg *crypto_rng_alg(struct crypto_rng *tfm)
> {
> return &crypto_rng_tfm(tfm)->__crt_alg->cra_rng;
> @@ -50,23 +115,71 @@ static inline struct rng_tfm *crypto_rng_crt(struct crypto_rng *tfm)
> return &crypto_rng_tfm(tfm)->crt_rng;
> }
>
> +/**
> + * The referenced random number generator handle is zeroized and subsequently
> + * freed.
> + *
> + * @tfm cipher handle to be freed
> + */
> static inline void crypto_free_rng(struct crypto_rng *tfm)
> {
> crypto_free_tfm(crypto_rng_tfm(tfm));
> }
>
> +/**
> + * This function fills the caller-allocated buffer with random numbers using the
> + * random number generator referenced by the cipher handle.
> + *
> + * @tfm cipher handle
> + * @rdata output buffer holding the random numbers
> + * @dlen length of the output buffer
> + *
> + * return value:
> + * > 0 function was successful and returns the number of generated bytes
> + * < 0 if an error occurred
> + */
> static inline int crypto_rng_get_bytes(struct crypto_rng *tfm,
> u8 *rdata, unsigned int dlen)
> {
> return crypto_rng_crt(tfm)->rng_gen_random(tfm, rdata, dlen);
> }
>
> +/**
> + * The reset function completely re-initializes the random number generator
> + * referenced by the cipher handle by clearing the current state. The new state
> + * is initialized with the caller provided seed or automatically, depending
> + * on the random number generator type (the ANSI X9.31 RNG requires
> + * caller-provided seed, the SP800-90A DRBGs perform an automatic seeding).
> + * The seed is provided with the. The provided seed should have the length of
dangling sentence...
> + * the seed size defined for the random number generator as defined by
> + * crypto_rng_seedsize.
> + *
> + * @tfm cipher handle
> + * @seed seed input data
> + * @slen length of the seed input data
> + *
> + * return value:
> + * 0 if the setting of the key was successful
> + * < 0 if an error occurred
> + */
> static inline int crypto_rng_reset(struct crypto_rng *tfm,
> u8 *seed, unsigned int slen)
> {
> return crypto_rng_crt(tfm)->rng_reset(tfm, seed, slen);
> }
>
> +/**
> + * The function returns the seed size for the random number generator
> + * referenced by the cipher handle. This value may be zero if the random
> + * number generator does not implement or require a reseeding. For example,
> + * the SP800-90A DRBGs implement an automated reseeding after reaching a
> + * pre-defined threshold.
> + *
> + * @tfm cipher handle
> + *
> + * return value:
> + * seed size for the random number generator
> + */
> static inline int crypto_rng_seedsize(struct crypto_rng *tfm)
> {
> return crypto_rng_alg(tfm)->seedsize;
Hi,
On 11/02/2014 12:35 PM, Stephan Mueller wrote:
> + * type:
> + - blkcipher for symmetric block ciphers
blkcipher for synchronous block ciphers
> + - ablkcipher for asymmetric block ciphers
ablkcipher for asynchronous block ciphers
> + - cipher for single block ciphers that may be used with an
> + additional template
> + - shash for symmetric message digest
shash for synchronous message digest
> + - ahash for asymmetric message digest
ahash for asynchronous message digest
T.
Hi Stephan,
On Sun, 2014-11-02 at 21:38 +0100, Stephan Mueller wrote:
> The API function calls exported by the kernel crypto API for SHASHes
> to be used by consumers are documented.
>
> Signed-off-by: Stephan Mueller <[email protected]>
> CC: Marek Vasut <[email protected]>
> ---
> include/crypto/hash.h | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 197 insertions(+)
>
> diff --git a/include/crypto/hash.h b/include/crypto/hash.h
> index 0d43dbc..7b3a621 100644
> --- a/include/crypto/hash.h
> +++ b/include/crypto/hash.h
> @@ -484,6 +484,33 @@ static inline void ahash_request_set_crypt(struct ahash_request *req,
> req->result = result;
> }
>
> +/**
> + * Synchronous message digest API to use the ciphers of type
> + * CRYPTO_ALG_TYPE_SHASH (listed as type "shash" in /proc/crypto)
> + *
> + * Considering the discussion of the state maintenance for the synchronous
> + * block cipher API, the message digest API is also able to maintain state
super picky comment, so can be ignored, but why mention block ciphers
here... everything after the comma sounds great to me.
> + * information for the caller. Though, the maintenance of the state is a bit
> + * different for the message digest API.
> + *
> + * The synchronous message digest API can store user-related context in in its
> + * shash_desc request data structure.
> + */
> +
> +/**
> + * Allocate a cipher handle for a message digest. The returned struct
> + * crypto_shash is the cipher handle that is required for any subsequent
> + * API invocation for that message digest.
> + *
> + * @alg_name is the cra_name / name or cra_driver_name / driver name of the
> + * message digest cipher
> + * @type specifies the type of the cipher (see Documentation/crypto/)
> + * @mask specifies the mask for the cipher (see Documentation/crypto/)
> + *
> + * return value:
> + * allocated cipher handle in case of success
> + * IS_ERR() is true in case of an error, PTR_ERR() returns the error code.
> + */
> struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type,
> u32 mask);
>
> @@ -492,6 +519,12 @@ static inline struct crypto_tfm *crypto_shash_tfm(struct crypto_shash *tfm)
> return &tfm->base;
> }
>
> +/**
> + * The referenced message digest handle is zeroized and subsequently
> + * freed.
> + *
> + * @tfm cipher handle to be freed
> + */
> static inline void crypto_free_shash(struct crypto_shash *tfm)
> {
> crypto_destroy_tfm(tfm, crypto_shash_tfm(tfm));
> @@ -503,6 +536,15 @@ static inline unsigned int crypto_shash_alignmask(
> return crypto_tfm_alg_alignmask(crypto_shash_tfm(tfm));
> }
>
> +/**
> + * The block size for the message digest cipher referenced with the cipher
> + * handle is returned.
> + *
> + * @tfm cipher handle
> + *
> + * return value:
> + * block size of cipher
> + */
> static inline unsigned int crypto_shash_blocksize(struct crypto_shash *tfm)
> {
> return crypto_tfm_alg_blocksize(crypto_shash_tfm(tfm));
> @@ -518,6 +560,15 @@ static inline struct shash_alg *crypto_shash_alg(struct crypto_shash *tfm)
> return __crypto_shash_alg(crypto_shash_tfm(tfm)->__crt_alg);
> }
>
> +/**
> + * The size for the message digest created by the message digest cipher
> + * referenced with the cipher handle is returned.
> + *
> + * @tfm cipher handle
> + *
> + * return value:
> + * block size of cipher
Should this be that it returns the digest size of the cipher?
> + */
> static inline unsigned int crypto_shash_digestsize(struct crypto_shash *tfm)
> {
> return crypto_shash_alg(tfm)->digestsize;
> @@ -543,6 +594,60 @@ static inline void crypto_shash_clear_flags(struct crypto_shash *tfm, u32 flags)
> crypto_tfm_clear_flags(crypto_shash_tfm(tfm), flags);
> }
>
> +/**
> + * The size of the operational state the cipher needs during operation is
> + * returned for the hash referenced with the cipher handle. This size is
> + * required to calculate the memory requirements to allow the caller allocating
> + * sufficient memory for operational state.
> + *
> + * The operational state is defined with struct shash_desc where the size of
> + * that data structure is to be calculated as
> + * sizeof(struct shash_desc) + crypto_shash_descsize(alg)
> + *
> + * @tfm cipher handle
> + *
> + * return value:
> + * size of the operational state
> + *
> + * The following example code shall illustrate the use of the operational
> + * state 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(struct crypto_shash *alg,
> + * const unsigned char *data, unsigned int datalen,
> + * unsigned char *digest) {
> + * struct sdesc *sdesc;
> + * int ret;
> + *
> + * sdesc = init_sdesc(alg);
> + * 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;
> + *}
> + */
> static inline unsigned int crypto_shash_descsize(struct crypto_shash *tfm)
> {
> return tfm->descsize;
> @@ -553,29 +658,121 @@ static inline void *shash_desc_ctx(struct shash_desc *desc)
> return desc->__ctx;
> }
>
> +/**
> + * The caller provided key is set for the message digest cipher. The cipher
Maybe "keyed message digest cipher" so reader immediately understands...
> + * handle must point to a keyed hash in order for this function to succeed.
> + *
> + * @tfm cipher handle
> + * @key buffer holding the key
> + * @keylen length of the key in bytes
> + *
> + * return value:
> + * 0 if the setting of the key was successful
> + * < 0 if an error occurred
> + */
> int crypto_shash_setkey(struct crypto_shash *tfm, const u8 *key,
> unsigned int keylen);
> +
> +/**
> + * This function is a "short-hand" for the function calls of crypto_shash_init,
> + * crypto_shash_update and crypto_shash_final. The parameters have the same
> + * meaning as discussed for those separate three functions.
> + *
> + * return value:
> + * 0 if the message digest creation was successful
> + * < 0 if an error occurred
> + */
> int crypto_shash_digest(struct shash_desc *desc, const u8 *data,
> unsigned int len, u8 *out);
>
> +/**
> + * This function exports the hash state of the operational state handle into the
> + * caller-allocated output buffer out which must have sufficient size (e.g. by
> + * calling crypto_shash_descsize).
> + *
> + * @desc reference to the operational state handle whose state is exported
> + * @out output buffer of sufficient size that can hold the hash state
> + *
> + * return value:
> + * 0 if the export creation was successful
> + * < 0 if an error occurred
> + */
> static inline int crypto_shash_export(struct shash_desc *desc, void *out)
> {
> return crypto_shash_alg(desc->tfm)->export(desc, out);
> }
>
> +/**
> + * This function imports the hash state into the operational state handle from
> + * the input buffer. That buffer should have been generated with the
> + * crypto_ahash_export function.
> + *
> + * @desc reference to the operational state handle the state imported into
> + * @in buffer holding the state
> + *
> + * return value:
> + * 0 if the import was successful
> + * < 0 if an error occurred
> + */
> static inline int crypto_shash_import(struct shash_desc *desc, const void *in)
> {
> return crypto_shash_alg(desc->tfm)->import(desc, in);
> }
>
> +/**
> + * The call (re-)initializes the message digest referenced by the
> + * operational state handle. Any potentially existing state created by
> + * previous operations is discarded.
> + *
> + * @desc operational state handle that is already filled
> + *
> + * return value:
> + * 0 if the message digest initialization was successful
> + * < 0 if an error occurred
> + */
> static inline int crypto_shash_init(struct shash_desc *desc)
> {
> return crypto_shash_alg(desc->tfm)->init(desc);
> }
>
> +/**
> + * Updates the message digest state of the operational state handle.
> + *
> + * @desc operational state handle that is already initialized
> + * @data input data to be added to the message digest
> + * @len length of the input data
> + *
> + * return value:
> + * 0 if the message digest update was successful
> + * < 0 if an error occurred
> + */
> int crypto_shash_update(struct shash_desc *desc, const u8 *data,
> unsigned int len);
> +
> +/**
> + * Finalize the message digest operation and create the message digest
> + * based on all data added to the cipher handle. The message digest is placed
> + * into the output buffer. The caller must ensure that the output buffer is
> + * large enough by using crypto_shash_digestsize.
> + *
> + * @desc operational state handle that is already filled with data
> + * @out output buffer filled with the message digest
> + *
> + * return value:
> + * 0 if the message digest creation was successful
> + * < 0 if an error occurred
> + */
> int crypto_shash_final(struct shash_desc *desc, u8 *out);
> +
> +/**
> + * This function is a "short-hand" for the function calls of
> + * crypto_shash_update and crypto_shash_final. The parameters have the same
> + * meaning as discussed for those separate functions.
> + *
> + * return value:
> + * 0 if the message digest creation was successful
> + * < 0 if an error occurred
> + */
> int crypto_shash_finup(struct shash_desc *desc, const u8 *data,
> unsigned int len, u8 *out);
>
regards,
Joy
Stephan,
On Mon, Nov 03, 2014 at 03:18:29PM +0100, Stephan Mueller wrote:
> Am Montag, 3. November 2014, 08:34:39 schrieb Jonathan Corbet:
> > These are all useful. But I wonder if it would be worth the effort to turn
> > this inti a proper docbook document that automatically has everything
> > together in one place?
>
> How do you suggest that is done? The API comments in the header file follow
> the Doxygen style. Note, Jason Cooper raised the concern that an API
> documentation separate from the code will surely deviate from the code
> relatively fast (although I do not really fear that as the kernel crypto API
> seems to be quite stable over the last years).
Agreed. My primary concern was adding it in such a way which
facilitates maintenance and keeping it in sync with the code. But as
you say, the crypto API doesn't change much.
thx,
Jason.
Am Mittwoch, 5. November 2014, 18:15:12 schrieb Tadeusz Struk:
Hi Tadeusz,
> Hi,
>
> On 11/02/2014 12:35 PM, Stephan Mueller wrote:
> > + * type:
> > + - blkcipher for symmetric block ciphers
>
> blkcipher for synchronous block ciphers
>
> > + - ablkcipher for asymmetric block ciphers
>
> ablkcipher for asynchronous block ciphers
>
> > + - cipher for single block ciphers that may be used with an
> > + additional template
> > + - shash for symmetric message digest
>
> shash for synchronous message digest
>
> > + - ahash for asymmetric message digest
>
> ahash for asynchronous message digest
>
> T.
Thanks a lot for this hint: I do not know how often I said "symmetric" or
"asymmetric" when in fact I meant synchronous and asynchronous....
Maybe I spent too much time in the crypto arena ;-)
--
Ciao
Stephan