2016-10-20 19:54:22 -07:00
|
|
|
Developing Cipher Algorithms
|
|
|
|
============================
|
|
|
|
|
|
|
|
Registering And Unregistering Transformation
|
|
|
|
--------------------------------------------
|
|
|
|
|
|
|
|
There are three distinct types of registration functions in the Crypto
|
|
|
|
API. One is used to register a generic cryptographic transformation,
|
|
|
|
while the other two are specific to HASH transformations and
|
|
|
|
COMPRESSion. We will discuss the latter two in a separate chapter, here
|
|
|
|
we will only look at the generic ones.
|
|
|
|
|
|
|
|
Before discussing the register functions, the data structure to be
|
|
|
|
filled with each, struct crypto_alg, must be considered -- see below
|
|
|
|
for a description of this data structure.
|
|
|
|
|
|
|
|
The generic registration functions can be found in
|
|
|
|
include/linux/crypto.h and their definition can be seen below. The
|
|
|
|
former function registers a single transformation, while the latter
|
|
|
|
works on an array of transformation descriptions. The latter is useful
|
|
|
|
when registering transformations in bulk, for example when a driver
|
|
|
|
implements multiple transformations.
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
int crypto_register_alg(struct crypto_alg *alg);
|
|
|
|
int crypto_register_algs(struct crypto_alg *algs, int count);
|
|
|
|
|
|
|
|
|
|
|
|
The counterparts to those functions are listed below.
|
|
|
|
|
|
|
|
::
|
|
|
|
|
2019-12-15 16:51:19 -07:00
|
|
|
void crypto_unregister_alg(struct crypto_alg *alg);
|
|
|
|
void crypto_unregister_algs(struct crypto_alg *algs, int count);
|
2016-10-20 19:54:22 -07:00
|
|
|
|
|
|
|
|
2019-12-15 16:51:19 -07:00
|
|
|
The registration functions return 0 on success, or a negative errno
|
|
|
|
value on failure. crypto_register_algs() succeeds only if it
|
|
|
|
successfully registered all the given algorithms; if it fails partway
|
|
|
|
through, then any changes are rolled back.
|
2016-10-20 19:54:22 -07:00
|
|
|
|
2019-12-15 16:51:19 -07:00
|
|
|
The unregistration functions always succeed, so they don't have a
|
|
|
|
return value. Don't try to unregister algorithms that aren't
|
|
|
|
currently registered.
|
2016-10-20 19:54:22 -07:00
|
|
|
|
|
|
|
Single-Block Symmetric Ciphers [CIPHER]
|
|
|
|
---------------------------------------
|
|
|
|
|
2019-12-06 21:19:37 -07:00
|
|
|
Example of transformations: aes, serpent, ...
|
2016-10-20 19:54:22 -07:00
|
|
|
|
|
|
|
This section describes the simplest of all transformation
|
|
|
|
implementations, that being the CIPHER type used for symmetric ciphers.
|
|
|
|
The CIPHER type is used for transformations which operate on exactly one
|
|
|
|
block at a time and there are no dependencies between blocks at all.
|
|
|
|
|
|
|
|
Registration specifics
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
The registration of [CIPHER] algorithm is specific in that struct
|
|
|
|
crypto_alg field .cra_type is empty. The .cra_u.cipher has to be
|
|
|
|
filled in with proper callbacks to implement this transformation.
|
|
|
|
|
|
|
|
See struct cipher_alg below.
|
|
|
|
|
|
|
|
Cipher Definition With struct cipher_alg
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
Struct cipher_alg defines a single block cipher.
|
|
|
|
|
|
|
|
Here are schematics of how these functions are called when operated from
|
|
|
|
other part of the kernel. Note that the .cia_setkey() call might happen
|
|
|
|
before or after any of these schematics happen, but must not happen
|
|
|
|
during any of these are in-flight.
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
KEY ---. PLAINTEXT ---.
|
|
|
|
v v
|
|
|
|
.cia_setkey() -> .cia_encrypt()
|
|
|
|
|
|
|
|
|
'-----> CIPHERTEXT
|
|
|
|
|
|
|
|
|
|
|
|
Please note that a pattern where .cia_setkey() is called multiple times
|
|
|
|
is also valid:
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
|
|
|
KEY1 --. PLAINTEXT1 --. KEY2 --. PLAINTEXT2 --.
|
|
|
|
v v v v
|
|
|
|
.cia_setkey() -> .cia_encrypt() -> .cia_setkey() -> .cia_encrypt()
|
|
|
|
| |
|
|
|
|
'---> CIPHERTEXT1 '---> CIPHERTEXT2
|
|
|
|
|
|
|
|
|
|
|
|
Multi-Block Ciphers
|
|
|
|
-------------------
|
|
|
|
|
2019-12-06 21:19:37 -07:00
|
|
|
Example of transformations: cbc(aes), chacha20, ...
|
2016-10-20 19:54:22 -07:00
|
|
|
|
|
|
|
This section describes the multi-block cipher transformation
|
|
|
|
implementations. The multi-block ciphers are used for transformations
|
|
|
|
which operate on scatterlists of data supplied to the transformation
|
|
|
|
functions. They output the result into a scatterlist of data as well.
|
|
|
|
|
|
|
|
Registration Specifics
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
The registration of multi-block cipher algorithms is one of the most
|
|
|
|
standard procedures throughout the crypto API.
|
|
|
|
|
|
|
|
Note, if a cipher implementation requires a proper alignment of data,
|
|
|
|
the caller should use the functions of crypto_skcipher_alignmask() to
|
|
|
|
identify a memory alignment mask. The kernel crypto API is able to
|
|
|
|
process requests that are unaligned. This implies, however, additional
|
|
|
|
overhead as the kernel crypto API needs to perform the realignment of
|
|
|
|
the data which may imply moving of data.
|
|
|
|
|
crypto: skcipher - remove the "blkcipher" algorithm type
Now that all "blkcipher" algorithms have been converted to "skcipher",
remove the blkcipher algorithm type.
The skcipher (symmetric key cipher) algorithm type was introduced a few
years ago to replace both blkcipher and ablkcipher (synchronous and
asynchronous block cipher). The advantages of skcipher include:
- A much less confusing name, since none of these algorithm types have
ever actually been for raw block ciphers, but rather for all
length-preserving encryption modes including block cipher modes of
operation, stream ciphers, and other length-preserving modes.
- It unified blkcipher and ablkcipher into a single algorithm type
which supports both synchronous and asynchronous implementations.
Note, blkcipher already operated only on scatterlists, so the fact
that skcipher does too isn't a regression in functionality.
- Better type safety by using struct skcipher_alg, struct
crypto_skcipher, etc. instead of crypto_alg, crypto_tfm, etc.
- It sometimes simplifies the implementations of algorithms.
Also, the blkcipher API was no longer being tested.
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2019-10-25 12:41:12 -07:00
|
|
|
Cipher Definition With struct skcipher_alg
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
2016-10-20 19:54:22 -07:00
|
|
|
|
crypto: skcipher - remove the "blkcipher" algorithm type
Now that all "blkcipher" algorithms have been converted to "skcipher",
remove the blkcipher algorithm type.
The skcipher (symmetric key cipher) algorithm type was introduced a few
years ago to replace both blkcipher and ablkcipher (synchronous and
asynchronous block cipher). The advantages of skcipher include:
- A much less confusing name, since none of these algorithm types have
ever actually been for raw block ciphers, but rather for all
length-preserving encryption modes including block cipher modes of
operation, stream ciphers, and other length-preserving modes.
- It unified blkcipher and ablkcipher into a single algorithm type
which supports both synchronous and asynchronous implementations.
Note, blkcipher already operated only on scatterlists, so the fact
that skcipher does too isn't a regression in functionality.
- Better type safety by using struct skcipher_alg, struct
crypto_skcipher, etc. instead of crypto_alg, crypto_tfm, etc.
- It sometimes simplifies the implementations of algorithms.
Also, the blkcipher API was no longer being tested.
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2019-10-25 12:41:12 -07:00
|
|
|
Struct skcipher_alg defines a multi-block cipher, or more generally, a
|
|
|
|
length-preserving symmetric cipher algorithm.
|
2016-10-20 19:54:22 -07:00
|
|
|
|
crypto: skcipher - remove the "blkcipher" algorithm type
Now that all "blkcipher" algorithms have been converted to "skcipher",
remove the blkcipher algorithm type.
The skcipher (symmetric key cipher) algorithm type was introduced a few
years ago to replace both blkcipher and ablkcipher (synchronous and
asynchronous block cipher). The advantages of skcipher include:
- A much less confusing name, since none of these algorithm types have
ever actually been for raw block ciphers, but rather for all
length-preserving encryption modes including block cipher modes of
operation, stream ciphers, and other length-preserving modes.
- It unified blkcipher and ablkcipher into a single algorithm type
which supports both synchronous and asynchronous implementations.
Note, blkcipher already operated only on scatterlists, so the fact
that skcipher does too isn't a regression in functionality.
- Better type safety by using struct skcipher_alg, struct
crypto_skcipher, etc. instead of crypto_alg, crypto_tfm, etc.
- It sometimes simplifies the implementations of algorithms.
Also, the blkcipher API was no longer being tested.
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2019-10-25 12:41:12 -07:00
|
|
|
Scatterlist handling
|
|
|
|
~~~~~~~~~~~~~~~~~~~~
|
2016-10-20 19:54:22 -07:00
|
|
|
|
crypto: skcipher - remove the "blkcipher" algorithm type
Now that all "blkcipher" algorithms have been converted to "skcipher",
remove the blkcipher algorithm type.
The skcipher (symmetric key cipher) algorithm type was introduced a few
years ago to replace both blkcipher and ablkcipher (synchronous and
asynchronous block cipher). The advantages of skcipher include:
- A much less confusing name, since none of these algorithm types have
ever actually been for raw block ciphers, but rather for all
length-preserving encryption modes including block cipher modes of
operation, stream ciphers, and other length-preserving modes.
- It unified blkcipher and ablkcipher into a single algorithm type
which supports both synchronous and asynchronous implementations.
Note, blkcipher already operated only on scatterlists, so the fact
that skcipher does too isn't a regression in functionality.
- Better type safety by using struct skcipher_alg, struct
crypto_skcipher, etc. instead of crypto_alg, crypto_tfm, etc.
- It sometimes simplifies the implementations of algorithms.
Also, the blkcipher API was no longer being tested.
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2019-10-25 12:41:12 -07:00
|
|
|
Some drivers will want to use the Generic ScatterWalk in case the
|
|
|
|
hardware needs to be fed separate chunks of the scatterlist which
|
|
|
|
contains the plaintext and will contain the ciphertext. Please refer
|
|
|
|
to the ScatterWalk interface offered by the Linux kernel scatter /
|
|
|
|
gather list implementation.
|
2016-10-20 19:54:22 -07:00
|
|
|
|
|
|
|
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:
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
|
|
|
::
|
|
|
|
|
2019-12-15 16:51:19 -07:00
|
|
|
void crypto_unregister_ahash(struct ahash_alg *alg);
|
2016-10-20 19:54:22 -07:00
|
|
|
|
2019-12-15 16:51:19 -07:00
|
|
|
void crypto_unregister_shash(struct shash_alg *alg);
|
|
|
|
void crypto_unregister_shashes(struct shash_alg *algs, int count);
|
2016-10-20 19:54:22 -07:00
|
|
|
|
|
|
|
|
|
|
|
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()
|
2022-10-27 12:35:44 -07:00
|
|
|
followed immediately by .final() is also a perfectly valid
|
2016-10-20 19:54:22 -07:00
|
|
|
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
|
|
|
|
|
2018-03-20 00:56:12 -07:00
|
|
|
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
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
2016-10-20 19:54:22 -07:00
|
|
|
|
|
|
|
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
|
crypto: ahash - remove support for nonzero alignmask
Currently, the ahash API checks the alignment of all key and result
buffers against the algorithm's declared alignmask, and for any
unaligned buffers it falls back to manually aligned temporary buffers.
This is virtually useless, however. First, since it does not apply to
the message, its effect is much more limited than e.g. is the case for
the alignmask for "skcipher". Second, the key and result buffers are
given as virtual addresses and cannot (in general) be DMA'ed into, so
drivers end up having to copy to/from them in software anyway. As a
result it's easy to use memcpy() or the unaligned access helpers.
The crypto_hash_walk_*() helper functions do use the alignmask to align
the message. But with one exception those are only used for shash
algorithms being exposed via the ahash API, not for native ahashes, and
aligning the message is not required in this case, especially now that
alignmask support has been removed from shash. The exception is the
n2_core driver, which doesn't set an alignmask.
In any case, no ahash algorithms actually set a nonzero alignmask
anymore. Therefore, remove support for it from ahash. The benefit is
that all the code to handle "misaligned" buffers in the ahash API goes
away, reducing the overhead of the ahash API.
This follows the same change that was made to shash.
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2023-10-22 01:10:44 -07:00
|
|
|
contains the input data.
|