| <?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 discuss 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> |