diff options
author | Stephan Mueller <smueller@chronox.de> | 2014-11-12 05:24:04 +0100 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2014-11-13 22:31:36 +0800 |
commit | 7d12993ed8901038bb46b27194e2ef5726d39f9a (patch) | |
tree | 0e4a7b13d54df4fcc06d5c961ff244f73e844e14 /Documentation | |
parent | ff2c3a3b8e57d088dcf740ab72f4f16eb2132257 (diff) | |
download | linux-7d12993ed8901038bb46b27194e2ef5726d39f9a.tar.gz linux-7d12993ed8901038bb46b27194e2ef5726d39f9a.tar.bz2 linux-7d12993ed8901038bb46b27194e2ef5726d39f9a.zip |
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 <marex@denx.de>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'Documentation')
-rw-r--r-- | Documentation/DocBook/crypto-API.tmpl | 1253 |
1 files changed, 1253 insertions, 0 deletions
diff --git a/Documentation/DocBook/crypto-API.tmpl b/Documentation/DocBook/crypto-API.tmpl new file mode 100644 index 000000000000..c763d30f4893 --- /dev/null +++ b/Documentation/DocBook/crypto-API.tmpl @@ -0,0 +1,1253 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" + "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []> + +<book id="KernelCryptoAPI"> + <bookinfo> + <title>Linux Kernel Crypto API</title> + + <authorgroup> + <author> + <firstname>Stephan</firstname> + <surname>Mueller</surname> + <affiliation> + <address> + <email>smueller@chronox.de</email> + </address> + </affiliation> + </author> + <author> + <firstname>Marek</firstname> + <surname>Vasut</surname> + <affiliation> + <address> + <email>marek@denx.de</email> + </address> + </affiliation> + </author> + </authorgroup> + + <copyright> + <year>2014</year> + <holder>Stephan Mueller</holder> + </copyright> + + + <legalnotice> + <para> + 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. + </para> + + <para> + 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. + </para> + + <para> + 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 + </para> + + <para> + For more details see the file COPYING in the source + distribution of Linux. + </para> + </legalnotice> + </bookinfo> + + <toc></toc> + + <chapter id="Intro"> + <title>Kernel Crypto API Interface Specification</title> + + <sect1><title>Introduction</title> + + <para> + 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. + </para> + + <para> + 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. + </para> + + <para> + 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. + </para> + + <para> + The kernel crypto API serves the following entity types: + + <itemizedlist> + <listitem> + <para>consumers requesting cryptographic services</para> + </listitem> + <listitem> + <para>data transformation implementations (typically ciphers) + that can be called by consumers using the kernel crypto + API</para> + </listitem> + </itemizedlist> + </para> + + <para> + 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). + </para> + + <para> + Note: The terms "transformation" and cipher algorithm are used + interchangably. + </para> + </sect1> + + <sect1><title>Terminology</title> + <para> + The transformation implementation is an actual code or interface + to hardware which implements a certain transformation with precisely + defined behavior. + </para> + + <para> + 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). + </para> + + <para> + 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: + </para> + + <orderedlist> + <listitem> + <para>Initialization of a cipher handle.</para> + </listitem> + <listitem> + <para>Execution of all intended cipher operations applicable + for the handle where the cipher handle must be furnished to + every API call.</para> + </listitem> + <listitem> + <para>Destruction of a cipher handle.</para> + </listitem> + </orderedlist> + + <para> + 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_*. + </para> + + <para> + The transformation context is private data associated with + the transformation object. + </para> + </sect1> + </chapter> + + <chapter id="Architecture"><title>Kernel Crypto API Architecture</title> + <sect1><title>Cipher algorithm types</title> + <para> + The kernel crypto API provides different API calls for the + following cipher types: + + <itemizedlist> + <listitem><para>Symmetric ciphers</para></listitem> + <listitem><para>AEAD ciphers</para></listitem> + <listitem><para>Message digest, including keyed message digest</para></listitem> + <listitem><para>Random number generation</para></listitem> + <listitem><para>User space interface</para></listitem> + </itemizedlist> + </para> + </sect1> + + <sect1><title>Ciphers And Templates</title> + <para> + 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. + </para> + + <para> + 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. + </para> + + <para> + A single block cipher may even be called with multiple templates. + However, templates cannot be used without a single cipher. + </para> + + <para> + See /proc/crypto and search for "name". For example: + + <itemizedlist> + <listitem><para>aes</para></listitem> + <listitem><para>ecb(aes)</para></listitem> + <listitem><para>cmac(aes)</para></listitem> + <listitem><para>ccm(aes)</para></listitem> + <listitem><para>rfc4106(gcm(aes))</para></listitem> + <listitem><para>sha1</para></listitem> + <listitem><para>hmac(sha1)</para></listitem> + <listitem><para>authenc(hmac(sha1),cbc(aes))</para></listitem> + </itemizedlist> + </para> + + <para> + In these examples, "aes" and "sha1" are the ciphers and all + others are the templates. + </para> + </sect1> + + <sect1><title>Synchronous And Asynchronous Operation</title> + <para> + The kernel crypto API provides synchronous and asynchronous + API operations. + </para> + + <para> + 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. + </para> + + <para> + 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. + </para> + </sect1> + + <sect1><title>Crypto API Cipher References And Priority</title> + <para> + A cipher is referenced by the caller with a string. That string + has the following semantics: + + <programlisting> + template(single block cipher) + </programlisting> + + 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 + + <programlisting> + template1(template2(single block cipher))) + </programlisting> + </para> + + <para> + 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. + </para> + + <para> + 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. + </para> + + <para> + 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: + </para> + + <itemizedlist> + <listitem> + <para>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)</para> + </listitem> + <listitem> + <para>driver: the unique name of the cipher -- this name can + be used by the cipher allocation API calls</para> + </listitem> + <listitem> + <para>module: the kernel module providing the cipher + implementation (or "kernel" for statically linked ciphers)</para> + </listitem> + <listitem> + <para>priority: the priority value of the cipher implementation</para> + </listitem> + <listitem> + <para>refcnt: the reference count of the respective cipher + (i.e. the number of current consumers of this cipher)</para> + </listitem> + <listitem> + <para>selftest: specification whether the self test for the + cipher passed</para> + </listitem> + <listitem> + <para>type: + <itemizedlist> + <listitem> + <para>blkcipher for synchronous block ciphers</para> + </listitem> + <listitem> + <para>ablkcipher for asynchronous block ciphers</para> + </listitem> + <listitem> + <para>cipher for single block ciphers that may be used with + an additional template</para> + </listitem> + <listitem> + <para>shash for synchronous message digest</para> + </listitem> + <listitem> + <para>ahash for asynchronous message digest</para> + </listitem> + <listitem> + <para>aead for AEAD cipher type</para> + </listitem> + <listitem> + <para>compression for compression type transformations</para> + </listitem> + <listitem> + <para>rng for random number generator</para> + </listitem> + <listitem> + <para>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)</para> + </listitem> + </itemizedlist> + </para> + </listitem> + <listitem> + <para>blocksize: blocksize of cipher in bytes</para> + </listitem> + <listitem> + <para>keysize: key size in bytes</para> + </listitem> + <listitem> + <para>ivsize: IV size in bytes</para> + </listitem> + <listitem> + <para>seedsize: required size of seed data for random number + generator</para> + </listitem> + <listitem> + <para>digestsize: output size of the message digest</para> + </listitem> + <listitem> + <para>geniv: IV generation type: + <itemizedlist> + <listitem> + <para>eseqiv for encrypted sequence number based IV + generation</para> + </listitem> + <listitem> + <para>seqiv for sequence number based IV generation</para> + </listitem> + <listitem> + <para>chainiv for chain iv generation</para> + </listitem> + <listitem> + <para><builtin> is a marker that the cipher implements + IV generation and handling as it is specific to the given + cipher</para> + </listitem> + </itemizedlist> + </para> + </listitem> + </itemizedlist> + </sect1> + + <sect1><title>Key Sizes</title> + <para> + 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. + </para> + </sect1> + + <sect1><title>Cipher Allocation Type And Masks</title> + <para> + 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). + </para> + + <para> + 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: + </para> + + <itemizedlist> + <listitem> + <para>CRYPTO_ALG_TYPE_CIPHER Single block cipher</para> + </listitem> + <listitem> + <para>CRYPTO_ALG_TYPE_COMPRESS Compression</para> + </listitem> + <listitem> + <para>CRYPTO_ALG_TYPE_AEAD Authenticated Encryption with + Associated Data (MAC)</para> + </listitem> + <listitem> + <para>CRYPTO_ALG_TYPE_BLKCIPHER Synchronous multi-block cipher</para> + </listitem> + <listitem> + <para>CRYPTO_ALG_TYPE_ABLKCIPHER Asynchronous multi-block cipher</para> + </listitem> + <listitem> + <para>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)</para> + </listitem> + <listitem> + <para>CRYPTO_ALG_TYPE_DIGEST Raw message digest</para> + </listitem> + <listitem> + <para>CRYPTO_ALG_TYPE_HASH Alias for CRYPTO_ALG_TYPE_DIGEST</para> + </listitem> + <listitem> + <para>CRYPTO_ALG_TYPE_SHASH Synchronous multi-block hash</para> + </listitem> + <listitem> + <para>CRYPTO_ALG_TYPE_AHASH Asynchronous multi-block hash</para> + </listitem> + <listitem> + <para>CRYPTO_ALG_TYPE_RNG Random Number Generation</para> + </listitem> + <listitem> + <para>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.</para> + </listitem> + </itemizedlist> + + <para> + 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. + </para> + + <para> + 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. + </para> + </sect1> + </chapter> + + <chapter id="Development"><title>Developing Cipher Algorithms</title> + <sect1><title>Registering And Unregistering Transformation</title> + <para> + 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. + </para> + + <para> + 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. + </para> + + <para> + 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. + </para> + + <programlisting> + int crypto_register_alg(struct crypto_alg *alg); + int crypto_register_algs(struct crypto_alg *algs, int count); + </programlisting> + + <para> + The counterparts to those functions are listed below. + </para> + + <programlisting> + int crypto_unregister_alg(struct crypto_alg *alg); + int crypto_unregister_algs(struct crypto_alg *algs, int count); + </programlisting> + + <para> + 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. + </para> + + <para> + 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. + </para> + </sect1> + + <sect1><title>Single-Block Symmetric Ciphers [CIPHER]</title> + <para> + Example of transformations: aes, arc4, ... + </para> + + <para> + 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. + </para> + + <sect2><title>Registration specifics</title> + <para> + 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. + </para> + + <para> + See struct cipher_alg below. + </para> + </sect2> + + <sect2><title>Cipher Definition With struct cipher_alg</title> + <para> + Struct cipher_alg defines a single block cipher. + </para> + + <para> + 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. + </para> + + <para> + <programlisting> + KEY ---. PLAINTEXT ---. + v v + .cia_setkey() -> .cia_encrypt() + | + '-----> CIPHERTEXT + </programlisting> + </para> + + <para> + Please note that a pattern where .cia_setkey() is called + multiple times is also valid: + </para> + + <para> + <programlisting> + + KEY1 --. PLAINTEXT1 --. KEY2 --. PLAINTEXT2 --. + v v v v + .cia_setkey() -> .cia_encrypt() -> .cia_setkey() -> .cia_encrypt() + | | + '---> CIPHERTEXT1 '---> CIPHERTEXT2 + </programlisting> + </para> + + </sect2> + </sect1> + + <sect1><title>Multi-Block Ciphers [BLKCIPHER] [ABLKCIPHER]</title> + <para> + Example of transformations: cbc(aes), ecb(arc4), ... + </para> + + <para> + 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. + </para> + + <sect2><title>Registration Specifics</title> + + <para> + The registration of [BLKCIPHER] or [ABLKCIPHER] algorithms + is one of the most standard procedures throughout the crypto API. + </para> + + <para> + 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. + </para> + </sect2> + + <sect2><title>Cipher Definition With struct blkcipher_alg and ablkcipher_alg</title> + <para> + Struct blkcipher_alg defines a synchronous block cipher whereas + struct ablkcipher_alg defines an asynchronous block cipher. + </para> + + <para> + 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]. + </para> + </sect2> + + <sect2><title>Specifics Of Asynchronous Multi-Block Cipher</title> + <para> + There are a couple of specifics to the [ABLKCIPHER] interface. + </para> + + <para> + 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. + </para> + </sect2> + </sect1> + + <sect1><title>Hashing [HASH]</title> + + <para> + Example of transformations: crc32, md5, sha1, sha256,... + </para> + + <sect2><title>Registering And Unregistering The Transformation</title> + + <para> + 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: + </para> + + <programlisting> + 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); + </programlisting> + + <para> + The respective counterparts for unregistering the HASH + transformation are as follows: + </para> + + <programlisting> + 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); + </programlisting> + </sect2> + + <sect2><title>Cipher Definition With struct shash_alg and ahash_alg</title> + <para> + 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. + </para> + + <programlisting> + 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 + </programlisting> + + <para> + Here is a schematic of how the .export()/.import() functions are + called when used from another part of the kernel. + </para> + + <programlisting> + 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 + </programlisting> + </sect2> + + <sect2><title>Specifics Of Asynchronous HASH Transformation</title> + <para> + 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. + </para> + </sect2> + </sect1> + </chapter> + + <chapter id="API"><title>Programming Interface</title> + <sect1><title>Block Cipher Context Data Structures</title> +!Pinclude/linux/crypto.h Block Cipher Context Data Structures +!Finclude/linux/crypto.h aead_request + </sect1> + <sect1><title>Block Cipher Algorithm Definitions</title> +!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 + </sect1> + <sect1><title>Asynchronous Block Cipher API</title> +!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 + </sect1> + <sect1><title>Asynchronous Cipher Request Handle</title> +!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 + </sect1> + <sect1><title>Authenticated Encryption With Associated Data (AEAD) Cipher API</title> +!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 + </sect1> + <sect1><title>Asynchronous AEAD Request Handle</title> +!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 + </sect1> + <sect1><title>Synchronous Block Cipher API</title> +!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 + </sect1> + <sect1><title>Single Block Cipher API</title> +!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 + </sect1> + <sect1><title>Synchronous Message Digest API</title> +!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 + </sect1> + <sect1><title>Message Digest Algorithm Definitions</title> +!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 + </sect1> + <sect1><title>Asynchronous Message Digest API</title> +!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 + </sect1> + <sect1><title>Asynchronous Hash Request Handle</title> +!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 + </sect1> + <sect1><title>Synchronous Message Digest API</title> +!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 + </sect1> + <sect1><title>Crypto API Random Number API</title> +!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 + </sect1> + </chapter> + + <chapter id="Code"><title>Code Examples</title> + <sect1><title>Code Example For Asynchronous Block Cipher Operation</title> + <programlisting> + +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; +} + </programlisting> + </sect1> + + <sect1><title>Code Example For Synchronous Block Cipher Operation</title> + <programlisting> + +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; +} + </programlisting> + </sect1> + + <sect1><title>Code Example For Use of Operational State Memory With SHASH</title> + <programlisting> + +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; +} + </programlisting> + </sect1> + + <sect1><title>Code Example For Random Number Generator Usage</title> + <programlisting> + +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; +} + </programlisting> + </sect1> + </chapter> + </book> |