162306a36Sopenharmony_ciDeveloping Cipher Algorithms 262306a36Sopenharmony_ci============================ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ciRegistering And Unregistering Transformation 562306a36Sopenharmony_ci-------------------------------------------- 662306a36Sopenharmony_ci 762306a36Sopenharmony_ciThere are three distinct types of registration functions in the Crypto 862306a36Sopenharmony_ciAPI. One is used to register a generic cryptographic transformation, 962306a36Sopenharmony_ciwhile the other two are specific to HASH transformations and 1062306a36Sopenharmony_ciCOMPRESSion. We will discuss the latter two in a separate chapter, here 1162306a36Sopenharmony_ciwe will only look at the generic ones. 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ciBefore discussing the register functions, the data structure to be 1462306a36Sopenharmony_cifilled with each, struct crypto_alg, must be considered -- see below 1562306a36Sopenharmony_cifor a description of this data structure. 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ciThe generic registration functions can be found in 1862306a36Sopenharmony_ciinclude/linux/crypto.h and their definition can be seen below. The 1962306a36Sopenharmony_ciformer function registers a single transformation, while the latter 2062306a36Sopenharmony_ciworks on an array of transformation descriptions. The latter is useful 2162306a36Sopenharmony_ciwhen registering transformations in bulk, for example when a driver 2262306a36Sopenharmony_ciimplements multiple transformations. 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci:: 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci int crypto_register_alg(struct crypto_alg *alg); 2762306a36Sopenharmony_ci int crypto_register_algs(struct crypto_alg *algs, int count); 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ciThe counterparts to those functions are listed below. 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci:: 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci void crypto_unregister_alg(struct crypto_alg *alg); 3562306a36Sopenharmony_ci void crypto_unregister_algs(struct crypto_alg *algs, int count); 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ciThe registration functions return 0 on success, or a negative errno 3962306a36Sopenharmony_civalue on failure. crypto_register_algs() succeeds only if it 4062306a36Sopenharmony_cisuccessfully registered all the given algorithms; if it fails partway 4162306a36Sopenharmony_cithrough, then any changes are rolled back. 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ciThe unregistration functions always succeed, so they don't have a 4462306a36Sopenharmony_cireturn value. Don't try to unregister algorithms that aren't 4562306a36Sopenharmony_cicurrently registered. 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ciSingle-Block Symmetric Ciphers [CIPHER] 4862306a36Sopenharmony_ci--------------------------------------- 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ciExample of transformations: aes, serpent, ... 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ciThis section describes the simplest of all transformation 5362306a36Sopenharmony_ciimplementations, that being the CIPHER type used for symmetric ciphers. 5462306a36Sopenharmony_ciThe CIPHER type is used for transformations which operate on exactly one 5562306a36Sopenharmony_ciblock at a time and there are no dependencies between blocks at all. 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ciRegistration specifics 5862306a36Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~ 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ciThe registration of [CIPHER] algorithm is specific in that struct 6162306a36Sopenharmony_cicrypto_alg field .cra_type is empty. The .cra_u.cipher has to be 6262306a36Sopenharmony_cifilled in with proper callbacks to implement this transformation. 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ciSee struct cipher_alg below. 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ciCipher Definition With struct cipher_alg 6762306a36Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ciStruct cipher_alg defines a single block cipher. 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ciHere are schematics of how these functions are called when operated from 7262306a36Sopenharmony_ciother part of the kernel. Note that the .cia_setkey() call might happen 7362306a36Sopenharmony_cibefore or after any of these schematics happen, but must not happen 7462306a36Sopenharmony_ciduring any of these are in-flight. 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci:: 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci KEY ---. PLAINTEXT ---. 7962306a36Sopenharmony_ci v v 8062306a36Sopenharmony_ci .cia_setkey() -> .cia_encrypt() 8162306a36Sopenharmony_ci | 8262306a36Sopenharmony_ci '-----> CIPHERTEXT 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ciPlease note that a pattern where .cia_setkey() is called multiple times 8662306a36Sopenharmony_ciis also valid: 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci:: 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci KEY1 --. PLAINTEXT1 --. KEY2 --. PLAINTEXT2 --. 9262306a36Sopenharmony_ci v v v v 9362306a36Sopenharmony_ci .cia_setkey() -> .cia_encrypt() -> .cia_setkey() -> .cia_encrypt() 9462306a36Sopenharmony_ci | | 9562306a36Sopenharmony_ci '---> CIPHERTEXT1 '---> CIPHERTEXT2 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ciMulti-Block Ciphers 9962306a36Sopenharmony_ci------------------- 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ciExample of transformations: cbc(aes), chacha20, ... 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ciThis section describes the multi-block cipher transformation 10462306a36Sopenharmony_ciimplementations. The multi-block ciphers are used for transformations 10562306a36Sopenharmony_ciwhich operate on scatterlists of data supplied to the transformation 10662306a36Sopenharmony_cifunctions. They output the result into a scatterlist of data as well. 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ciRegistration Specifics 10962306a36Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~ 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ciThe registration of multi-block cipher algorithms is one of the most 11262306a36Sopenharmony_cistandard procedures throughout the crypto API. 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ciNote, if a cipher implementation requires a proper alignment of data, 11562306a36Sopenharmony_cithe caller should use the functions of crypto_skcipher_alignmask() to 11662306a36Sopenharmony_ciidentify a memory alignment mask. The kernel crypto API is able to 11762306a36Sopenharmony_ciprocess requests that are unaligned. This implies, however, additional 11862306a36Sopenharmony_cioverhead as the kernel crypto API needs to perform the realignment of 11962306a36Sopenharmony_cithe data which may imply moving of data. 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ciCipher Definition With struct skcipher_alg 12262306a36Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ciStruct skcipher_alg defines a multi-block cipher, or more generally, a 12562306a36Sopenharmony_cilength-preserving symmetric cipher algorithm. 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ciScatterlist handling 12862306a36Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~ 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ciSome drivers will want to use the Generic ScatterWalk in case the 13162306a36Sopenharmony_cihardware needs to be fed separate chunks of the scatterlist which 13262306a36Sopenharmony_cicontains the plaintext and will contain the ciphertext. Please refer 13362306a36Sopenharmony_cito the ScatterWalk interface offered by the Linux kernel scatter / 13462306a36Sopenharmony_cigather list implementation. 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ciHashing [HASH] 13762306a36Sopenharmony_ci-------------- 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ciExample of transformations: crc32, md5, sha1, sha256,... 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ciRegistering And Unregistering The Transformation 14262306a36Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ciThere are multiple ways to register a HASH transformation, depending on 14562306a36Sopenharmony_ciwhether the transformation is synchronous [SHASH] or asynchronous 14662306a36Sopenharmony_ci[AHASH] and the amount of HASH transformations we are registering. You 14762306a36Sopenharmony_cican find the prototypes defined in include/crypto/internal/hash.h: 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci:: 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci int crypto_register_ahash(struct ahash_alg *alg); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci int crypto_register_shash(struct shash_alg *alg); 15462306a36Sopenharmony_ci int crypto_register_shashes(struct shash_alg *algs, int count); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ciThe respective counterparts for unregistering the HASH transformation 15862306a36Sopenharmony_ciare as follows: 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci:: 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci void crypto_unregister_ahash(struct ahash_alg *alg); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci void crypto_unregister_shash(struct shash_alg *alg); 16562306a36Sopenharmony_ci void crypto_unregister_shashes(struct shash_alg *algs, int count); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ciCipher Definition With struct shash_alg and ahash_alg 16962306a36Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ciHere are schematics of how these functions are called when operated from 17262306a36Sopenharmony_ciother part of the kernel. Note that the .setkey() call might happen 17362306a36Sopenharmony_cibefore or after any of these schematics happen, but must not happen 17462306a36Sopenharmony_ciduring any of these are in-flight. Please note that calling .init() 17562306a36Sopenharmony_cifollowed immediately by .final() is also a perfectly valid 17662306a36Sopenharmony_citransformation. 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci:: 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci I) DATA -----------. 18162306a36Sopenharmony_ci v 18262306a36Sopenharmony_ci .init() -> .update() -> .final() ! .update() might not be called 18362306a36Sopenharmony_ci ^ | | at all in this scenario. 18462306a36Sopenharmony_ci '----' '---> HASH 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci II) DATA -----------.-----------. 18762306a36Sopenharmony_ci v v 18862306a36Sopenharmony_ci .init() -> .update() -> .finup() ! .update() may not be called 18962306a36Sopenharmony_ci ^ | | at all in this scenario. 19062306a36Sopenharmony_ci '----' '---> HASH 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci III) DATA -----------. 19362306a36Sopenharmony_ci v 19462306a36Sopenharmony_ci .digest() ! The entire process is handled 19562306a36Sopenharmony_ci | by the .digest() call. 19662306a36Sopenharmony_ci '---------------> HASH 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ciHere is a schematic of how the .export()/.import() functions are called 20062306a36Sopenharmony_ciwhen used from another part of the kernel. 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci:: 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci KEY--. DATA--. 20562306a36Sopenharmony_ci v v ! .update() may not be called 20662306a36Sopenharmony_ci .setkey() -> .init() -> .update() -> .export() at all in this scenario. 20762306a36Sopenharmony_ci ^ | | 20862306a36Sopenharmony_ci '-----' '--> PARTIAL_HASH 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci ----------- other transformations happen here ----------- 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci PARTIAL_HASH--. DATA1--. 21362306a36Sopenharmony_ci v v 21462306a36Sopenharmony_ci .import -> .update() -> .final() ! .update() may not be called 21562306a36Sopenharmony_ci ^ | | at all in this scenario. 21662306a36Sopenharmony_ci '----' '--> HASH1 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci PARTIAL_HASH--. DATA2-. 21962306a36Sopenharmony_ci v v 22062306a36Sopenharmony_ci .import -> .finup() 22162306a36Sopenharmony_ci | 22262306a36Sopenharmony_ci '---------------> HASH2 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ciNote that it is perfectly legal to "abandon" a request object: 22562306a36Sopenharmony_ci- call .init() and then (as many times) .update() 22662306a36Sopenharmony_ci- _not_ call any of .final(), .finup() or .export() at any point in future 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ciIn other words implementations should mind the resource allocation and clean-up. 22962306a36Sopenharmony_ciNo resources related to request objects should remain allocated after a call 23062306a36Sopenharmony_cito .init() or .update(), since there might be no chance to free them. 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ciSpecifics Of Asynchronous HASH Transformation 23462306a36Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ciSome of the drivers will want to use the Generic ScatterWalk in case the 23762306a36Sopenharmony_ciimplementation needs to be fed separate chunks of the scatterlist which 23862306a36Sopenharmony_cicontains the input data. The buffer containing the resulting hash will 23962306a36Sopenharmony_cialways be properly aligned to .cra_alignmask so there is no need to 24062306a36Sopenharmony_ciworry about this. 241