[LINUX] Developing Cipher Algorithms (2/2)


Docs » Linux Kernel Crypto API » Developing Cipher Algorithms

Hashing [HASH] 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:

There are multiple ways to register a HASH transformation. It depends on whether the transformations are synchronous or [SHASH], asynchronous [AHASH], and the number of HASH transformations you are trying to register. Pros and live can be found at 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:

Each method for unregistering HASH transformation is as follows.

void crypto_unregister_ahash(struct ahash_alg *alg);

void crypto_unregister_shash(struct shash_alg *alg);
void 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.

Below is a diagram of how these functions are called when processing is called from other parts of the kernel. Note that the call to .setkry () occurs before or after these figures occur. However, it is not called during processing. Note that calling .finish () immediately after .init () is also called is also a valid conversion.

I)   DATA -----------.
      .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 -----------.
                 .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.

Here's what the .export () /. import () functions are called when using the rest 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 -----------

              v          v
          .import -> .update() -> .final()     ! .update() may not be called
                      ^    |         |           at all in this scenario.
                      '----'         '--> HASH1

              v         v
          .import -> .finup()
                        '---------------> HASH2

Note that it is perfectly legal to “abandon” a request object: - call .init() and then (as many times) .update() - not call any of .final(), .finup() or .export() at any point in future

Note that "destroying" the requested object is a complete expectation. Call init () (and multiple times) to call .update (), and finally .final () or export () at any time in the future.

In other words implementations should mind the resource allocation and clean-up. No resources related to request objects should remain allocated after a call to .init() or .update(), since there might be no chance to free them.

In other words, the implementation must be careful about resource allocation and clean-up. Resources unrelated to the request object must reserve the rest after calling .init () or .update (), and they have no chance of being released.

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.

Some drivers try to use Generic ScatterWalk in cases where implementation is required to handle the split chunks of the scatterlist contained in the input data. The buffer containing the resulting hash is always properly placed in the .cra_alignmask and should not be considered.

Originally, it is a part of the Linux Kernel source code, so it will be treated as GPLv2 (recognition that it should be).


Licensing documentation

The following describes the license of the Linux kernel source code (GPLv2), how to properly mark the license of individual files in the source tree, as well as links to the full license text.


Recommended Posts

Developing Cipher Algorithms (1/2)
Developing Cipher Algorithms (2/2)