cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

devel-algos.rst (8991B)


      1Developing Cipher Algorithms
      2============================
      3
      4Registering And Unregistering Transformation
      5--------------------------------------------
      6
      7There are three distinct types of registration functions in the Crypto
      8API. One is used to register a generic cryptographic transformation,
      9while the other two are specific to HASH transformations and
     10COMPRESSion. We will discuss the latter two in a separate chapter, here
     11we will only look at the generic ones.
     12
     13Before discussing the register functions, the data structure to be
     14filled with each, struct crypto_alg, must be considered -- see below
     15for a description of this data structure.
     16
     17The generic registration functions can be found in
     18include/linux/crypto.h and their definition can be seen below. The
     19former function registers a single transformation, while the latter
     20works on an array of transformation descriptions. The latter is useful
     21when registering transformations in bulk, for example when a driver
     22implements multiple transformations.
     23
     24::
     25
     26       int crypto_register_alg(struct crypto_alg *alg);
     27       int crypto_register_algs(struct crypto_alg *algs, int count);
     28
     29
     30The counterparts to those functions are listed below.
     31
     32::
     33
     34       void crypto_unregister_alg(struct crypto_alg *alg);
     35       void crypto_unregister_algs(struct crypto_alg *algs, int count);
     36
     37
     38The registration functions return 0 on success, or a negative errno
     39value on failure.  crypto_register_algs() succeeds only if it
     40successfully registered all the given algorithms; if it fails partway
     41through, then any changes are rolled back.
     42
     43The unregistration functions always succeed, so they don't have a
     44return value.  Don't try to unregister algorithms that aren't
     45currently registered.
     46
     47Single-Block Symmetric Ciphers [CIPHER]
     48---------------------------------------
     49
     50Example of transformations: aes, serpent, ...
     51
     52This section describes the simplest of all transformation
     53implementations, that being the CIPHER type used for symmetric ciphers.
     54The CIPHER type is used for transformations which operate on exactly one
     55block at a time and there are no dependencies between blocks at all.
     56
     57Registration specifics
     58~~~~~~~~~~~~~~~~~~~~~~
     59
     60The registration of [CIPHER] algorithm is specific in that struct
     61crypto_alg field .cra_type is empty. The .cra_u.cipher has to be
     62filled in with proper callbacks to implement this transformation.
     63
     64See struct cipher_alg below.
     65
     66Cipher Definition With struct cipher_alg
     67~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     68
     69Struct cipher_alg defines a single block cipher.
     70
     71Here are schematics of how these functions are called when operated from
     72other part of the kernel. Note that the .cia_setkey() call might happen
     73before or after any of these schematics happen, but must not happen
     74during any of these are in-flight.
     75
     76::
     77
     78             KEY ---.    PLAINTEXT ---.
     79                    v                 v
     80              .cia_setkey() -> .cia_encrypt()
     81                                      |
     82                                      '-----> CIPHERTEXT
     83
     84
     85Please note that a pattern where .cia_setkey() is called multiple times
     86is also valid:
     87
     88::
     89
     90
     91      KEY1 --.    PLAINTEXT1 --.         KEY2 --.    PLAINTEXT2 --.
     92             v                 v                v                 v
     93       .cia_setkey() -> .cia_encrypt() -> .cia_setkey() -> .cia_encrypt()
     94                               |                                  |
     95                               '---> CIPHERTEXT1                  '---> CIPHERTEXT2
     96
     97
     98Multi-Block Ciphers
     99-------------------
    100
    101Example of transformations: cbc(aes), chacha20, ...
    102
    103This section describes the multi-block cipher transformation
    104implementations. The multi-block ciphers are used for transformations
    105which operate on scatterlists of data supplied to the transformation
    106functions. They output the result into a scatterlist of data as well.
    107
    108Registration Specifics
    109~~~~~~~~~~~~~~~~~~~~~~
    110
    111The registration of multi-block cipher algorithms is one of the most
    112standard procedures throughout the crypto API.
    113
    114Note, if a cipher implementation requires a proper alignment of data,
    115the caller should use the functions of crypto_skcipher_alignmask() to
    116identify a memory alignment mask. The kernel crypto API is able to
    117process requests that are unaligned. This implies, however, additional
    118overhead as the kernel crypto API needs to perform the realignment of
    119the data which may imply moving of data.
    120
    121Cipher Definition With struct skcipher_alg
    122~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    123
    124Struct skcipher_alg defines a multi-block cipher, or more generally, a
    125length-preserving symmetric cipher algorithm.
    126
    127Scatterlist handling
    128~~~~~~~~~~~~~~~~~~~~
    129
    130Some drivers will want to use the Generic ScatterWalk in case the
    131hardware needs to be fed separate chunks of the scatterlist which
    132contains the plaintext and will contain the ciphertext. Please refer
    133to the ScatterWalk interface offered by the Linux kernel scatter /
    134gather list implementation.
    135
    136Hashing [HASH]
    137--------------
    138
    139Example of transformations: crc32, md5, sha1, sha256,...
    140
    141Registering And Unregistering The Transformation
    142~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    143
    144There are multiple ways to register a HASH transformation, depending on
    145whether the transformation is synchronous [SHASH] or asynchronous
    146[AHASH] and the amount of HASH transformations we are registering. You
    147can find the prototypes defined in include/crypto/internal/hash.h:
    148
    149::
    150
    151       int crypto_register_ahash(struct ahash_alg *alg);
    152
    153       int crypto_register_shash(struct shash_alg *alg);
    154       int crypto_register_shashes(struct shash_alg *algs, int count);
    155
    156
    157The respective counterparts for unregistering the HASH transformation
    158are as follows:
    159
    160::
    161
    162       void crypto_unregister_ahash(struct ahash_alg *alg);
    163
    164       void crypto_unregister_shash(struct shash_alg *alg);
    165       void crypto_unregister_shashes(struct shash_alg *algs, int count);
    166
    167
    168Cipher Definition With struct shash_alg and ahash_alg
    169~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    170
    171Here are schematics of how these functions are called when operated from
    172other part of the kernel. Note that the .setkey() call might happen
    173before or after any of these schematics happen, but must not happen
    174during any of these are in-flight. Please note that calling .init()
    175followed immediately by .finish() is also a perfectly valid
    176transformation.
    177
    178::
    179
    180       I)   DATA -----------.
    181                            v
    182             .init() -> .update() -> .final()      ! .update() might not be called
    183                         ^    |         |            at all in this scenario.
    184                         '----'         '---> HASH
    185
    186       II)  DATA -----------.-----------.
    187                            v           v
    188             .init() -> .update() -> .finup()      ! .update() may not be called
    189                         ^    |         |            at all in this scenario.
    190                         '----'         '---> HASH
    191
    192       III) DATA -----------.
    193                            v
    194                        .digest()                  ! The entire process is handled
    195                            |                        by the .digest() call.
    196                            '---------------> HASH
    197
    198
    199Here is a schematic of how the .export()/.import() functions are called
    200when used from another part of the kernel.
    201
    202::
    203
    204       KEY--.                 DATA--.
    205            v                       v                  ! .update() may not be called
    206        .setkey() -> .init() -> .update() -> .export()   at all in this scenario.
    207                                 ^     |         |
    208                                 '-----'         '--> PARTIAL_HASH
    209
    210       ----------- other transformations happen here -----------
    211
    212       PARTIAL_HASH--.   DATA1--.
    213                     v          v
    214                 .import -> .update() -> .final()     ! .update() may not be called
    215                             ^    |         |           at all in this scenario.
    216                             '----'         '--> HASH1
    217
    218       PARTIAL_HASH--.   DATA2-.
    219                     v         v
    220                 .import -> .finup()
    221                               |
    222                               '---------------> HASH2
    223
    224Note that it is perfectly legal to "abandon" a request object:
    225- call .init() and then (as many times) .update()
    226- _not_ call any of .final(), .finup() or .export() at any point in future
    227
    228In other words implementations should mind the resource allocation and clean-up.
    229No resources related to request objects should remain allocated after a call
    230to .init() or .update(), since there might be no chance to free them.
    231
    232
    233Specifics Of Asynchronous HASH Transformation
    234~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    235
    236Some of the drivers will want to use the Generic ScatterWalk in case the
    237implementation needs to be fed separate chunks of the scatterlist which
    238contains the input data. The buffer containing the resulting hash will
    239always be properly aligned to .cra_alignmask so there is no need to
    240worry about this.