239 lines · plain
1Developing Cipher Algorithms2============================3 4Registering And Unregistering Transformation5--------------------------------------------6 7There are three distinct types of registration functions in the Crypto8API. One is used to register a generic cryptographic transformation,9while the other two are specific to HASH transformations and10COMPRESSion. We will discuss the latter two in a separate chapter, here11we will only look at the generic ones.12 13Before discussing the register functions, the data structure to be14filled with each, struct crypto_alg, must be considered -- see below15for a description of this data structure.16 17The generic registration functions can be found in18include/linux/crypto.h and their definition can be seen below. The19former function registers a single transformation, while the latter20works on an array of transformation descriptions. The latter is useful21when registering transformations in bulk, for example when a driver22implements multiple transformations.23 24::25 26 int crypto_register_alg(struct crypto_alg *alg);27 int crypto_register_algs(struct crypto_alg *algs, int count);28 29 30The counterparts to those functions are listed below.31 32::33 34 void crypto_unregister_alg(struct crypto_alg *alg);35 void crypto_unregister_algs(struct crypto_alg *algs, int count);36 37 38The registration functions return 0 on success, or a negative errno39value on failure. crypto_register_algs() succeeds only if it40successfully registered all the given algorithms; if it fails partway41through, then any changes are rolled back.42 43The unregistration functions always succeed, so they don't have a44return value. Don't try to unregister algorithms that aren't45currently registered.46 47Single-Block Symmetric Ciphers [CIPHER]48---------------------------------------49 50Example of transformations: aes, serpent, ...51 52This section describes the simplest of all transformation53implementations, that being the CIPHER type used for symmetric ciphers.54The CIPHER type is used for transformations which operate on exactly one55block at a time and there are no dependencies between blocks at all.56 57Registration specifics58~~~~~~~~~~~~~~~~~~~~~~59 60The registration of [CIPHER] algorithm is specific in that struct61crypto_alg field .cra_type is empty. The .cra_u.cipher has to be62filled in with proper callbacks to implement this transformation.63 64See struct cipher_alg below.65 66Cipher Definition With struct cipher_alg67~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~68 69Struct cipher_alg defines a single block cipher.70 71Here are schematics of how these functions are called when operated from72other part of the kernel. Note that the .cia_setkey() call might happen73before or after any of these schematics happen, but must not happen74during any of these are in-flight.75 76::77 78 KEY ---. PLAINTEXT ---.79 v v80 .cia_setkey() -> .cia_encrypt()81 |82 '-----> CIPHERTEXT83 84 85Please note that a pattern where .cia_setkey() is called multiple times86is also valid:87 88::89 90 91 KEY1 --. PLAINTEXT1 --. KEY2 --. PLAINTEXT2 --.92 v v v v93 .cia_setkey() -> .cia_encrypt() -> .cia_setkey() -> .cia_encrypt()94 | |95 '---> CIPHERTEXT1 '---> CIPHERTEXT296 97 98Multi-Block Ciphers99-------------------100 101Example of transformations: cbc(aes), chacha20, ...102 103This section describes the multi-block cipher transformation104implementations. The multi-block ciphers are used for transformations105which operate on scatterlists of data supplied to the transformation106functions. They output the result into a scatterlist of data as well.107 108Registration Specifics109~~~~~~~~~~~~~~~~~~~~~~110 111The registration of multi-block cipher algorithms is one of the most112standard procedures throughout the crypto API.113 114Note, if a cipher implementation requires a proper alignment of data,115the caller should use the functions of crypto_skcipher_alignmask() to116identify a memory alignment mask. The kernel crypto API is able to117process requests that are unaligned. This implies, however, additional118overhead as the kernel crypto API needs to perform the realignment of119the data which may imply moving of data.120 121Cipher Definition With struct skcipher_alg122~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~123 124Struct skcipher_alg defines a multi-block cipher, or more generally, a125length-preserving symmetric cipher algorithm.126 127Scatterlist handling128~~~~~~~~~~~~~~~~~~~~129 130Some drivers will want to use the Generic ScatterWalk in case the131hardware needs to be fed separate chunks of the scatterlist which132contains the plaintext and will contain the ciphertext. Please refer133to the ScatterWalk interface offered by the Linux kernel scatter /134gather list implementation.135 136Hashing [HASH]137--------------138 139Example of transformations: crc32, md5, sha1, sha256,...140 141Registering And Unregistering The Transformation142~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~143 144There are multiple ways to register a HASH transformation, depending on145whether the transformation is synchronous [SHASH] or asynchronous146[AHASH] and the amount of HASH transformations we are registering. You147can find the prototypes defined in include/crypto/internal/hash.h:148 149::150 151 int crypto_register_ahash(struct ahash_alg *alg);152 153 int crypto_register_shash(struct shash_alg *alg);154 int crypto_register_shashes(struct shash_alg *algs, int count);155 156 157The respective counterparts for unregistering the HASH transformation158are as follows:159 160::161 162 void crypto_unregister_ahash(struct ahash_alg *alg);163 164 void crypto_unregister_shash(struct shash_alg *alg);165 void crypto_unregister_shashes(struct shash_alg *algs, int count);166 167 168Cipher Definition With struct shash_alg and ahash_alg169~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~170 171Here are schematics of how these functions are called when operated from172other part of the kernel. Note that the .setkey() call might happen173before or after any of these schematics happen, but must not happen174during any of these are in-flight. Please note that calling .init()175followed immediately by .final() is also a perfectly valid176transformation.177 178::179 180 I) DATA -----------.181 v182 .init() -> .update() -> .final() ! .update() might not be called183 ^ | | at all in this scenario.184 '----' '---> HASH185 186 II) DATA -----------.-----------.187 v v188 .init() -> .update() -> .finup() ! .update() may not be called189 ^ | | at all in this scenario.190 '----' '---> HASH191 192 III) DATA -----------.193 v194 .digest() ! The entire process is handled195 | by the .digest() call.196 '---------------> HASH197 198 199Here is a schematic of how the .export()/.import() functions are called200when used from another part of the kernel.201 202::203 204 KEY--. DATA--.205 v v ! .update() may not be called206 .setkey() -> .init() -> .update() -> .export() at all in this scenario.207 ^ | |208 '-----' '--> PARTIAL_HASH209 210 ----------- other transformations happen here -----------211 212 PARTIAL_HASH--. DATA1--.213 v v214 .import -> .update() -> .final() ! .update() may not be called215 ^ | | at all in this scenario.216 '----' '--> HASH1217 218 PARTIAL_HASH--. DATA2-.219 v v220 .import -> .finup()221 |222 '---------------> HASH2223 224Note that it is perfectly legal to "abandon" a request object:225- call .init() and then (as many times) .update()226- _not_ call any of .final(), .finup() or .export() at any point in future227 228In other words implementations should mind the resource allocation and clean-up.229No resources related to request objects should remain allocated after a call230to .init() or .update(), since there might be no chance to free them.231 232 233Specifics Of Asynchronous HASH Transformation234~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~235 236Some of the drivers will want to use the Generic ScatterWalk in case the237implementation needs to be fed separate chunks of the scatterlist which238contains the input data.239