From 7d12993ed8901038bb46b27194e2ef5726d39f9a Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Wed, 12 Nov 2014 05:24:04 +0100 Subject: [PATCH] crypto: doc - crypto API high level spec 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 * source code examples CC: Marek Vasut Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- Documentation/DocBook/crypto-API.tmpl | 1253 +++++++++++++++++++++++++++++++++ 1 file changed, 1253 insertions(+) create mode 100644 Documentation/DocBook/crypto-API.tmpl diff --git a/Documentation/DocBook/crypto-API.tmpl b/Documentation/DocBook/crypto-API.tmpl new file mode 100644 index 0000000..c763d30 --- /dev/null +++ b/Documentation/DocBook/crypto-API.tmpl @@ -0,0 +1,1253 @@ + + + + + + Linux Kernel Crypto API + + + + Stephan + Mueller + +
+ smueller@chronox.de +
+
+
+ + Marek + Vasut + +
+ marek@denx.de +
+
+
+
+ + + 2014 + Stephan Mueller + + + + + + This documentation is free software; you can redistribute + it and/or modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later + version. + + + + This program 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 General Public License for more details. + + + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + + + + For more details see the file COPYING in the source + distribution of Linux. + + +
+ + + + + Kernel Crypto API Interface Specification + + Introduction + + + 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 "transformations". + Therefore, a cipher handle variable usually has the name "tfm". + Besides cryptographic operations, the kernel crypto API also knows + compression transformations 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 structure that contains transformation objects may also be + referred to as a "cipher handle". Such a cipher handle is always + subject to the following phases that are reflected in the API calls + applicable to such a cipher handle: + + + + + Initialization of a cipher handle. + + + Execution of all intended cipher operations applicable + for the handle where the cipher handle must be furnished to + every API call. + + + Destruction of a cipher handle. + + + + + When using the initialization API calls, a cipher handle is + created and returned to the consumer. Therefore, please refer + to all initialization API calls that refer to the data + structure type a consumer is expected to receive and subsequently + to use. The initialization API calls have all the same naming + conventions of crypto_alloc_*. + + + + 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. + + + + See /proc/crypto and search for "name". For example: + + + aes + ecb(aes) + cmac(aes) + ccm(aes) + rfc4106(gcm(aes)) + sha1 + hmac(sha1) + authenc(hmac(sha1),cbc(aes)) + + + + + In these examples, "aes" and "sha1" are the ciphers and all + others are the templates. + + + + 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. + + + + 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. However, + that list does not specify all possible permutations of + templates and ciphers. Each block listed in /proc/crypto may + contain the following information -- if one of the components + listed as follows are not applicable to a cipher, it is not + displayed: + + + + + 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 (all names listed above are + examples for such generic names) + + + 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 synchronous block ciphers + + + ablkcipher for asynchronous block ciphers + + + cipher for single block ciphers that may be used with + an additional template + + + shash for synchronous message digest + + + ahash for asynchronous message digest + + + aead for AEAD cipher type + + + compression for compression type transformations + + + rng for random number generator + + + givcipher for cipher with associated IV generator + (see the geniv entry below for the specification of the + IV generator type used by the cipher implementation) + + + + + + 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 Single 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 Asynchronous multi-block + cipher packed together with an IV generator (see geniv field + in the /proc/crypto listing for the known IV generators) + + + 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 Enhanced version of + CRYPTO_ALG_TYPE_COMPRESS allowing for segmented compression / + decompression instead of performing the operation on one + segment only. CRYPTO_ALG_TYPE_PCOMPRESS is intended to replace + CRYPTO_ALG_TYPE_COMPRESS once existing consumers are converted. + + + + + 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 search the kernel crypto API can perform 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. + + + + Before discussing the register functions, the data structure + to be filled with each, struct crypto_alg, must be considered + -- see below for a description of this data structure. + + + + 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. A return + code of zero implies success. Any return code < 0 implies + an error. + + + + 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. Note, the caller has no way of + knowing which cipher implementations have successfully + registered. If this is important to know, the caller should + loop through the different implementations using the single + instance *_alg functions for each individual implementation. + + + + Single-Block Symmetric Ciphers [CIPHER] + + Example of transformations: aes, arc4, ... + + + + This section describes the simplest of all transformation + implementations, that being the CIPHER type used for symmetric + ciphers. 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. + + + + See struct cipher_alg below. + + + + Cipher Definition With struct cipher_alg + + Struct cipher_alg defines a single block cipher. + + + + 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. + + + + Note, if a cipher implementation requires a proper alignment + of data, the caller should use the functions of + crypto_blkcipher_alignmask() or crypto_ablkcipher_alignmask() + respectively to identify a memory alignment mask. The kernel + crypto API is able to process requests that are unaligned. + This implies, however, additional overhead as the kernel + crypto API needs to perform the realignment of the data which + may imply moving of data. + + + + Cipher Definition With struct blkcipher_alg and ablkcipher_alg + + Struct blkcipher_alg defines a synchronous block cipher whereas + struct ablkcipher_alg defines an asynchronous block cipher. + + + + 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 + to the ScatterWalk interface offered by the Linux kernel + scatter / gather list implementation. + + + + + 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); + + + + Cipher Definition With struct shash_alg and ahash_alg + + 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 immediately 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 + + + + Specifics Of Asynchronous HASH Transformation + + Some of the drivers will want to use the Generic ScatterWalk + in case the implementation 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. + + + + + + Programming Interface + Block Cipher Context Data Structures +!Pinclude/linux/crypto.h Block Cipher Context Data Structures +!Finclude/linux/crypto.h aead_request + + Block Cipher Algorithm Definitions +!Pinclude/linux/crypto.h Block Cipher Algorithm Definitions +!Finclude/linux/crypto.h crypto_alg +!Finclude/linux/crypto.h ablkcipher_alg +!Finclude/linux/crypto.h aead_alg +!Finclude/linux/crypto.h blkcipher_alg +!Finclude/linux/crypto.h cipher_alg +!Finclude/linux/crypto.h rng_alg + + Asynchronous Block Cipher API +!Pinclude/linux/crypto.h Asynchronous Block Cipher API +!Finclude/linux/crypto.h crypto_alloc_ablkcipher +!Finclude/linux/crypto.h crypto_free_ablkcipher +!Finclude/linux/crypto.h crypto_has_ablkcipher +!Finclude/linux/crypto.h crypto_ablkcipher_ivsize +!Finclude/linux/crypto.h crypto_ablkcipher_blocksize +!Finclude/linux/crypto.h crypto_ablkcipher_setkey +!Finclude/linux/crypto.h crypto_ablkcipher_reqtfm +!Finclude/linux/crypto.h crypto_ablkcipher_encrypt +!Finclude/linux/crypto.h crypto_ablkcipher_decrypt + + Asynchronous Cipher Request Handle +!Pinclude/linux/crypto.h Asynchronous Cipher Request Handle +!Finclude/linux/crypto.h crypto_ablkcipher_reqsize +!Finclude/linux/crypto.h ablkcipher_request_set_tfm +!Finclude/linux/crypto.h ablkcipher_request_alloc +!Finclude/linux/crypto.h ablkcipher_request_free +!Finclude/linux/crypto.h ablkcipher_request_set_callback +!Finclude/linux/crypto.h ablkcipher_request_set_crypt + + Authenticated Encryption With Associated Data (AEAD) Cipher API +!Pinclude/linux/crypto.h Authenticated Encryption With Associated Data (AEAD) Cipher API +!Finclude/linux/crypto.h crypto_alloc_aead +!Finclude/linux/crypto.h crypto_free_aead +!Finclude/linux/crypto.h crypto_aead_ivsize +!Finclude/linux/crypto.h crypto_aead_authsize +!Finclude/linux/crypto.h crypto_aead_blocksize +!Finclude/linux/crypto.h crypto_aead_setkey +!Finclude/linux/crypto.h crypto_aead_setauthsize +!Finclude/linux/crypto.h crypto_aead_encrypt +!Finclude/linux/crypto.h crypto_aead_decrypt + + Asynchronous AEAD Request Handle +!Pinclude/linux/crypto.h Asynchronous AEAD Request Handle +!Finclude/linux/crypto.h crypto_aead_reqsize +!Finclude/linux/crypto.h aead_request_set_tfm +!Finclude/linux/crypto.h aead_request_alloc +!Finclude/linux/crypto.h aead_request_free +!Finclude/linux/crypto.h aead_request_set_callback +!Finclude/linux/crypto.h aead_request_set_crypt +!Finclude/linux/crypto.h aead_request_set_assoc + + Synchronous Block Cipher API +!Pinclude/linux/crypto.h Synchronous Block Cipher API +!Finclude/linux/crypto.h crypto_alloc_blkcipher +!Finclude/linux/crypto.h crypto_free_blkcipher +!Finclude/linux/crypto.h crypto_has_blkcipher +!Finclude/linux/crypto.h crypto_blkcipher_name +!Finclude/linux/crypto.h crypto_blkcipher_ivsize +!Finclude/linux/crypto.h crypto_blkcipher_blocksize +!Finclude/linux/crypto.h crypto_blkcipher_setkey +!Finclude/linux/crypto.h crypto_blkcipher_encrypt +!Finclude/linux/crypto.h crypto_blkcipher_encrypt_iv +!Finclude/linux/crypto.h crypto_blkcipher_decrypt +!Finclude/linux/crypto.h crypto_blkcipher_decrypt_iv +!Finclude/linux/crypto.h crypto_blkcipher_set_iv +!Finclude/linux/crypto.h crypto_blkcipher_get_iv + + Single Block Cipher API +!Pinclude/linux/crypto.h Single Block Cipher API +!Finclude/linux/crypto.h crypto_alloc_cipher +!Finclude/linux/crypto.h crypto_free_cipher +!Finclude/linux/crypto.h crypto_has_cipher +!Finclude/linux/crypto.h crypto_cipher_blocksize +!Finclude/linux/crypto.h crypto_cipher_setkey +!Finclude/linux/crypto.h crypto_cipher_encrypt_one +!Finclude/linux/crypto.h crypto_cipher_decrypt_one + + Synchronous Message Digest API +!Pinclude/linux/crypto.h Synchronous Message Digest API +!Finclude/linux/crypto.h crypto_alloc_hash +!Finclude/linux/crypto.h crypto_free_hash +!Finclude/linux/crypto.h crypto_has_hash +!Finclude/linux/crypto.h crypto_hash_blocksize +!Finclude/linux/crypto.h crypto_hash_digestsize +!Finclude/linux/crypto.h crypto_hash_init +!Finclude/linux/crypto.h crypto_hash_update +!Finclude/linux/crypto.h crypto_hash_final +!Finclude/linux/crypto.h crypto_hash_digest +!Finclude/linux/crypto.h crypto_hash_setkey + + Message Digest Algorithm Definitions +!Pinclude/crypto/hash.h Message Digest Algorithm Definitions +!Finclude/crypto/hash.h hash_alg_common +!Finclude/crypto/hash.h ahash_alg +!Finclude/crypto/hash.h shash_alg + + Asynchronous Message Digest API +!Pinclude/crypto/hash.h Asynchronous Message Digest API +!Finclude/crypto/hash.h crypto_alloc_ahash +!Finclude/crypto/hash.h crypto_free_ahash +!Finclude/crypto/hash.h crypto_ahash_init +!Finclude/crypto/hash.h crypto_ahash_digestsize +!Finclude/crypto/hash.h crypto_ahash_reqtfm +!Finclude/crypto/hash.h crypto_ahash_reqsize +!Finclude/crypto/hash.h crypto_ahash_setkey +!Finclude/crypto/hash.h crypto_ahash_finup +!Finclude/crypto/hash.h crypto_ahash_final +!Finclude/crypto/hash.h crypto_ahash_digest +!Finclude/crypto/hash.h crypto_ahash_export +!Finclude/crypto/hash.h crypto_ahash_import + + Asynchronous Hash Request Handle +!Pinclude/crypto/hash.h Asynchronous Hash Request Handle +!Finclude/crypto/hash.h ahash_request_set_tfm +!Finclude/crypto/hash.h ahash_request_alloc +!Finclude/crypto/hash.h ahash_request_free +!Finclude/crypto/hash.h ahash_request_set_callback +!Finclude/crypto/hash.h ahash_request_set_crypt + + Synchronous Message Digest API +!Pinclude/crypto/hash.h Synchronous Message Digest API +!Finclude/crypto/hash.h crypto_alloc_shash +!Finclude/crypto/hash.h crypto_free_shash +!Finclude/crypto/hash.h crypto_shash_blocksize +!Finclude/crypto/hash.h crypto_shash_digestsize +!Finclude/crypto/hash.h crypto_shash_descsize +!Finclude/crypto/hash.h crypto_shash_setkey +!Finclude/crypto/hash.h crypto_shash_digest +!Finclude/crypto/hash.h crypto_shash_export +!Finclude/crypto/hash.h crypto_shash_import +!Finclude/crypto/hash.h crypto_shash_init +!Finclude/crypto/hash.h crypto_shash_update +!Finclude/crypto/hash.h crypto_shash_final +!Finclude/crypto/hash.h crypto_shash_finup + + Crypto API Random Number API +!Pinclude/crypto/rng.h Random number generator API +!Finclude/crypto/rng.h crypto_alloc_rng +!Finclude/crypto/rng.h crypto_rng_alg +!Finclude/crypto/rng.h crypto_free_rng +!Finclude/crypto/rng.h crypto_rng_get_bytes +!Finclude/crypto/rng.h crypto_rng_reset +!Finclude/crypto/rng.h crypto_rng_seedsize +!Cinclude/crypto/rng.h + + + + Code Examples + Code Example For Asynchronous Block Cipher Operation + + +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; +} + + + + Code Example For Synchronous Block Cipher Operation + + +static int test_blkcipher(void) +{ + struct crypto_blkcipher *blkcipher = NULL; + char *cipher = "cbc(aes)"; + // AES 128 + charkey = +"\x12\x34\x56\x78\x90\xab\xcd\xef\x12\x34\x56\x78\x90\xab\xcd\xef"; + chariv = +"\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; +} + + + + Code Example For Use of Operational State Memory With SHASH + + +struct sdesc { + struct shash_desc shash; + char ctx[]; +}; + +static struct sdescinit_sdesc(struct crypto_shash *alg) +{ + struct sdescsdesc; + 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_shashalg, + const unsigned chardata, unsigned int datalen, + unsigned chardigest) { + struct sdescsdesc; + 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; +} + + + + Code Example For Random Number Generator Usage + + +static int get_random_numbers(u8 *buf, unsigned int len) +{ + struct crypto_rngrng = NULL; + chardrbg = "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; +} + + + +
-- 2.7.4