Hashing [HASH]

Registering And Unregistering The Transformation
Cipher Definition With struct shash_alg and ahash_alg
Specifics Of Asynchronous HASH Transformation

Example of transformations: crc32, md5, sha1, sha256,...

Registering And Unregistering The Transformation

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:

   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);
     

The respective counterparts for unregistering the HASH transformation are as follows:

   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);
     

Cipher Definition With struct shash_alg and ahash_alg

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.

   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
     

Here is a schematic of how the .export()/.import() functions are called when used from another part of the kernel.

   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
     

Specifics Of Asynchronous HASH Transformation

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.