18c2ecf20Sopenharmony_ciDeveloping Cipher Algorithms 28c2ecf20Sopenharmony_ci============================ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ciRegistering And Unregistering Transformation 58c2ecf20Sopenharmony_ci-------------------------------------------- 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ciThere are three distinct types of registration functions in the Crypto 88c2ecf20Sopenharmony_ciAPI. One is used to register a generic cryptographic transformation, 98c2ecf20Sopenharmony_ciwhile the other two are specific to HASH transformations and 108c2ecf20Sopenharmony_ciCOMPRESSion. We will discuss the latter two in a separate chapter, here 118c2ecf20Sopenharmony_ciwe will only look at the generic ones. 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ciBefore discussing the register functions, the data structure to be 148c2ecf20Sopenharmony_cifilled with each, struct crypto_alg, must be considered -- see below 158c2ecf20Sopenharmony_cifor a description of this data structure. 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ciThe generic registration functions can be found in 188c2ecf20Sopenharmony_ciinclude/linux/crypto.h and their definition can be seen below. The 198c2ecf20Sopenharmony_ciformer function registers a single transformation, while the latter 208c2ecf20Sopenharmony_ciworks on an array of transformation descriptions. The latter is useful 218c2ecf20Sopenharmony_ciwhen registering transformations in bulk, for example when a driver 228c2ecf20Sopenharmony_ciimplements multiple transformations. 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci:: 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci int crypto_register_alg(struct crypto_alg *alg); 278c2ecf20Sopenharmony_ci int crypto_register_algs(struct crypto_alg *algs, int count); 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ciThe counterparts to those functions are listed below. 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci:: 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci void crypto_unregister_alg(struct crypto_alg *alg); 358c2ecf20Sopenharmony_ci void crypto_unregister_algs(struct crypto_alg *algs, int count); 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ciThe registration functions return 0 on success, or a negative errno 398c2ecf20Sopenharmony_civalue on failure. crypto_register_algs() succeeds only if it 408c2ecf20Sopenharmony_cisuccessfully registered all the given algorithms; if it fails partway 418c2ecf20Sopenharmony_cithrough, then any changes are rolled back. 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ciThe unregistration functions always succeed, so they don't have a 448c2ecf20Sopenharmony_cireturn value. Don't try to unregister algorithms that aren't 458c2ecf20Sopenharmony_cicurrently registered. 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ciSingle-Block Symmetric Ciphers [CIPHER] 488c2ecf20Sopenharmony_ci--------------------------------------- 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ciExample of transformations: aes, serpent, ... 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ciThis section describes the simplest of all transformation 538c2ecf20Sopenharmony_ciimplementations, that being the CIPHER type used for symmetric ciphers. 548c2ecf20Sopenharmony_ciThe CIPHER type is used for transformations which operate on exactly one 558c2ecf20Sopenharmony_ciblock at a time and there are no dependencies between blocks at all. 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ciRegistration specifics 588c2ecf20Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~ 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ciThe registration of [CIPHER] algorithm is specific in that struct 618c2ecf20Sopenharmony_cicrypto_alg field .cra_type is empty. The .cra_u.cipher has to be 628c2ecf20Sopenharmony_cifilled in with proper callbacks to implement this transformation. 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ciSee struct cipher_alg below. 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ciCipher Definition With struct cipher_alg 678c2ecf20Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ciStruct cipher_alg defines a single block cipher. 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ciHere are schematics of how these functions are called when operated from 728c2ecf20Sopenharmony_ciother part of the kernel. Note that the .cia_setkey() call might happen 738c2ecf20Sopenharmony_cibefore or after any of these schematics happen, but must not happen 748c2ecf20Sopenharmony_ciduring any of these are in-flight. 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci:: 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci KEY ---. PLAINTEXT ---. 798c2ecf20Sopenharmony_ci v v 808c2ecf20Sopenharmony_ci .cia_setkey() -> .cia_encrypt() 818c2ecf20Sopenharmony_ci | 828c2ecf20Sopenharmony_ci '-----> CIPHERTEXT 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ciPlease note that a pattern where .cia_setkey() is called multiple times 868c2ecf20Sopenharmony_ciis also valid: 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci:: 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci KEY1 --. PLAINTEXT1 --. KEY2 --. PLAINTEXT2 --. 928c2ecf20Sopenharmony_ci v v v v 938c2ecf20Sopenharmony_ci .cia_setkey() -> .cia_encrypt() -> .cia_setkey() -> .cia_encrypt() 948c2ecf20Sopenharmony_ci | | 958c2ecf20Sopenharmony_ci '---> CIPHERTEXT1 '---> CIPHERTEXT2 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ciMulti-Block Ciphers 998c2ecf20Sopenharmony_ci------------------- 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ciExample of transformations: cbc(aes), chacha20, ... 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ciThis section describes the multi-block cipher transformation 1048c2ecf20Sopenharmony_ciimplementations. The multi-block ciphers are used for transformations 1058c2ecf20Sopenharmony_ciwhich operate on scatterlists of data supplied to the transformation 1068c2ecf20Sopenharmony_cifunctions. They output the result into a scatterlist of data as well. 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ciRegistration Specifics 1098c2ecf20Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~ 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ciThe registration of multi-block cipher algorithms is one of the most 1128c2ecf20Sopenharmony_cistandard procedures throughout the crypto API. 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ciNote, if a cipher implementation requires a proper alignment of data, 1158c2ecf20Sopenharmony_cithe caller should use the functions of crypto_skcipher_alignmask() to 1168c2ecf20Sopenharmony_ciidentify a memory alignment mask. The kernel crypto API is able to 1178c2ecf20Sopenharmony_ciprocess requests that are unaligned. This implies, however, additional 1188c2ecf20Sopenharmony_cioverhead as the kernel crypto API needs to perform the realignment of 1198c2ecf20Sopenharmony_cithe data which may imply moving of data. 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ciCipher Definition With struct skcipher_alg 1228c2ecf20Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ciStruct skcipher_alg defines a multi-block cipher, or more generally, a 1258c2ecf20Sopenharmony_cilength-preserving symmetric cipher algorithm. 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ciScatterlist handling 1288c2ecf20Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~ 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ciSome drivers will want to use the Generic ScatterWalk in case the 1318c2ecf20Sopenharmony_cihardware needs to be fed separate chunks of the scatterlist which 1328c2ecf20Sopenharmony_cicontains the plaintext and will contain the ciphertext. Please refer 1338c2ecf20Sopenharmony_cito the ScatterWalk interface offered by the Linux kernel scatter / 1348c2ecf20Sopenharmony_cigather list implementation. 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ciHashing [HASH] 1378c2ecf20Sopenharmony_ci-------------- 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ciExample of transformations: crc32, md5, sha1, sha256,... 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ciRegistering And Unregistering The Transformation 1428c2ecf20Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ciThere are multiple ways to register a HASH transformation, depending on 1458c2ecf20Sopenharmony_ciwhether the transformation is synchronous [SHASH] or asynchronous 1468c2ecf20Sopenharmony_ci[AHASH] and the amount of HASH transformations we are registering. You 1478c2ecf20Sopenharmony_cican find the prototypes defined in include/crypto/internal/hash.h: 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci:: 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci int crypto_register_ahash(struct ahash_alg *alg); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci int crypto_register_shash(struct shash_alg *alg); 1548c2ecf20Sopenharmony_ci int crypto_register_shashes(struct shash_alg *algs, int count); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ciThe respective counterparts for unregistering the HASH transformation 1588c2ecf20Sopenharmony_ciare as follows: 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci:: 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci void crypto_unregister_ahash(struct ahash_alg *alg); 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci void crypto_unregister_shash(struct shash_alg *alg); 1658c2ecf20Sopenharmony_ci void crypto_unregister_shashes(struct shash_alg *algs, int count); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ciCipher Definition With struct shash_alg and ahash_alg 1698c2ecf20Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ciHere are schematics of how these functions are called when operated from 1728c2ecf20Sopenharmony_ciother part of the kernel. Note that the .setkey() call might happen 1738c2ecf20Sopenharmony_cibefore or after any of these schematics happen, but must not happen 1748c2ecf20Sopenharmony_ciduring any of these are in-flight. Please note that calling .init() 1758c2ecf20Sopenharmony_cifollowed immediately by .finish() is also a perfectly valid 1768c2ecf20Sopenharmony_citransformation. 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci:: 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci I) DATA -----------. 1818c2ecf20Sopenharmony_ci v 1828c2ecf20Sopenharmony_ci .init() -> .update() -> .final() ! .update() might not be called 1838c2ecf20Sopenharmony_ci ^ | | at all in this scenario. 1848c2ecf20Sopenharmony_ci '----' '---> HASH 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci II) DATA -----------.-----------. 1878c2ecf20Sopenharmony_ci v v 1888c2ecf20Sopenharmony_ci .init() -> .update() -> .finup() ! .update() may not be called 1898c2ecf20Sopenharmony_ci ^ | | at all in this scenario. 1908c2ecf20Sopenharmony_ci '----' '---> HASH 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci III) DATA -----------. 1938c2ecf20Sopenharmony_ci v 1948c2ecf20Sopenharmony_ci .digest() ! The entire process is handled 1958c2ecf20Sopenharmony_ci | by the .digest() call. 1968c2ecf20Sopenharmony_ci '---------------> HASH 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ciHere is a schematic of how the .export()/.import() functions are called 2008c2ecf20Sopenharmony_ciwhen used from another part of the kernel. 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci:: 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci KEY--. DATA--. 2058c2ecf20Sopenharmony_ci v v ! .update() may not be called 2068c2ecf20Sopenharmony_ci .setkey() -> .init() -> .update() -> .export() at all in this scenario. 2078c2ecf20Sopenharmony_ci ^ | | 2088c2ecf20Sopenharmony_ci '-----' '--> PARTIAL_HASH 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci ----------- other transformations happen here ----------- 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci PARTIAL_HASH--. DATA1--. 2138c2ecf20Sopenharmony_ci v v 2148c2ecf20Sopenharmony_ci .import -> .update() -> .final() ! .update() may not be called 2158c2ecf20Sopenharmony_ci ^ | | at all in this scenario. 2168c2ecf20Sopenharmony_ci '----' '--> HASH1 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci PARTIAL_HASH--. DATA2-. 2198c2ecf20Sopenharmony_ci v v 2208c2ecf20Sopenharmony_ci .import -> .finup() 2218c2ecf20Sopenharmony_ci | 2228c2ecf20Sopenharmony_ci '---------------> HASH2 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ciNote that it is perfectly legal to "abandon" a request object: 2258c2ecf20Sopenharmony_ci- call .init() and then (as many times) .update() 2268c2ecf20Sopenharmony_ci- _not_ call any of .final(), .finup() or .export() at any point in future 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ciIn other words implementations should mind the resource allocation and clean-up. 2298c2ecf20Sopenharmony_ciNo resources related to request objects should remain allocated after a call 2308c2ecf20Sopenharmony_cito .init() or .update(), since there might be no chance to free them. 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ciSpecifics Of Asynchronous HASH Transformation 2348c2ecf20Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ciSome of the drivers will want to use the Generic ScatterWalk in case the 2378c2ecf20Sopenharmony_ciimplementation needs to be fed separate chunks of the scatterlist which 2388c2ecf20Sopenharmony_cicontains the input data. The buffer containing the resulting hash will 2398c2ecf20Sopenharmony_cialways be properly aligned to .cra_alignmask so there is no need to 2408c2ecf20Sopenharmony_ciworry about this. 241