Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4d2fa8b4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull crypto updates from Herbert Xu:
 "Here is the crypto update for 5.3:

  API:
   - Test shash interface directly in testmgr
   - cra_driver_name is now mandatory

  Algorithms:
   - Replace arc4 crypto_cipher with library helper
   - Implement 5 way interleave for ECB, CBC and CTR on arm64
   - Add xxhash
   - Add continuous self-test on noise source to drbg
   - Update jitter RNG

  Drivers:
   - Add support for SHA204A random number generator
   - Add support for 7211 in iproc-rng200
   - Fix fuzz test failures in inside-secure
   - Fix fuzz test failures in talitos
   - Fix fuzz test failures in qat"

* 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (143 commits)
  crypto: stm32/hash - remove interruptible condition for dma
  crypto: stm32/hash - Fix hmac issue more than 256 bytes
  crypto: stm32/crc32 - rename driver file
  crypto: amcc - remove memset after dma_alloc_coherent
  crypto: ccp - Switch to SPDX license identifiers
  crypto: ccp - Validate the the error value used to index error messages
  crypto: doc - Fix formatting of new crypto engine content
  crypto: doc - Add parameter documentation
  crypto: arm64/aes-ce - implement 5 way interleave for ECB, CBC and CTR
  crypto: arm64/aes-ce - add 5 way interleave routines
  crypto: talitos - drop icv_ool
  crypto: talitos - fix hash on SEC1.
  crypto: talitos - move struct talitos_edesc into talitos.h
  lib/scatterlist: Fix mapping iterator when sg->offset is greater than PAGE_SIZE
  crypto/NX: Set receive window credits to max number of CRBs in RxFIFO
  crypto: asymmetric_keys - select CRYPTO_HASH where needed
  crypto: serpent - mark __serpent_setkey_sbox noinline
  crypto: testmgr - dynamically allocate crypto_shash
  crypto: testmgr - dynamically allocate testvec_config
  crypto: talitos - eliminate unneeded 'done' functions at build time
  ...
parents 8b681508 f3880a23
Loading
Loading
Loading
Loading
+77 −99
Original line number Diff line number Diff line
@@ -4,111 +4,89 @@ Code Examples
Code Example For Symmetric Key Cipher Operation
-----------------------------------------------

::


    /* tie all data structures together */
    struct skcipher_def {
        struct scatterlist sg;
        struct crypto_skcipher *tfm;
        struct skcipher_request *req;
        struct crypto_wait wait;
    };

    /* Perform cipher operation */
    static unsigned int test_skcipher_encdec(struct skcipher_def *sk,
                         int enc)
    {
        int rc;

        if (enc)
            rc = crypto_wait_req(crypto_skcipher_encrypt(sk->req), &sk->wait);
        else
            rc = crypto_wait_req(crypto_skcipher_decrypt(sk->req), &sk->wait);
This code encrypts some data with AES-256-XTS.  For sake of example,
all inputs are random bytes, the encryption is done in-place, and it's
assumed the code is running in a context where it can sleep.

	if (rc)
		pr_info("skcipher encrypt returned with result %d\n", rc);

        return rc;
    }
::

    /* Initialize and trigger cipher operation */
    static int test_skcipher(void)
    {
        struct skcipher_def sk;
        struct crypto_skcipher *skcipher = NULL;
            struct crypto_skcipher *tfm = NULL;
            struct skcipher_request *req = NULL;
        char *scratchpad = NULL;
        char *ivdata = NULL;
        unsigned char key[32];
        int ret = -EFAULT;

        skcipher = crypto_alloc_skcipher("cbc-aes-aesni", 0, 0);
        if (IS_ERR(skcipher)) {
            pr_info("could not allocate skcipher handle\n");
            return PTR_ERR(skcipher);
            u8 *data = NULL;
            const size_t datasize = 512; /* data size in bytes */
            struct scatterlist sg;
            DECLARE_CRYPTO_WAIT(wait);
            u8 iv[16];  /* AES-256-XTS takes a 16-byte IV */
            u8 key[64]; /* AES-256-XTS takes a 64-byte key */
            int err;

            /*
             * Allocate a tfm (a transformation object) and set the key.
             *
             * In real-world use, a tfm and key are typically used for many
             * encryption/decryption operations.  But in this example, we'll just do a
             * single encryption operation with it (which is not very efficient).
             */

            tfm = crypto_alloc_skcipher("xts(aes)", 0, 0);
            if (IS_ERR(tfm)) {
                    pr_err("Error allocating xts(aes) handle: %ld\n", PTR_ERR(tfm));
                    return PTR_ERR(tfm);
            }

        req = skcipher_request_alloc(skcipher, GFP_KERNEL);
        if (!req) {
            pr_info("could not allocate skcipher request\n");
            ret = -ENOMEM;
            get_random_bytes(key, sizeof(key));
            err = crypto_skcipher_setkey(tfm, key, sizeof(key));
            if (err) {
                    pr_err("Error setting key: %d\n", err);
                    goto out;
            }

        skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
                          crypto_req_done,
                          &sk.wait);

        /* AES 256 with random key */
        get_random_bytes(&key, 32);
        if (crypto_skcipher_setkey(skcipher, key, 32)) {
            pr_info("key could not be set\n");
            ret = -EAGAIN;
            /* Allocate a request object */
            req = skcipher_request_alloc(tfm, GFP_KERNEL);
            if (!req) {
                    err = -ENOMEM;
                    goto out;
            }

        /* IV will be random */
        ivdata = kmalloc(16, GFP_KERNEL);
        if (!ivdata) {
            pr_info("could not allocate ivdata\n");
            /* Prepare the input data */
            data = kmalloc(datasize, GFP_KERNEL);
            if (!data) {
                    err = -ENOMEM;
                    goto out;
            }
        get_random_bytes(ivdata, 16);

        /* Input data will be random */
        scratchpad = kmalloc(16, GFP_KERNEL);
        if (!scratchpad) {
            pr_info("could not allocate scratchpad\n");
            get_random_bytes(data, datasize);

            /* Initialize the IV */
            get_random_bytes(iv, sizeof(iv));

            /*
             * Encrypt the data in-place.
             *
             * For simplicity, in this example we wait for the request to complete
             * before proceeding, even if the underlying implementation is asynchronous.
             *
             * To decrypt instead of encrypt, just change crypto_skcipher_encrypt() to
             * crypto_skcipher_decrypt().
             */
            sg_init_one(&sg, data, datasize);
            skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
                                               CRYPTO_TFM_REQ_MAY_SLEEP,
                                          crypto_req_done, &wait);
            skcipher_request_set_crypt(req, &sg, &sg, datasize, iv);
            err = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
            if (err) {
                    pr_err("Error encrypting data: %d\n", err);
                    goto out;
            }
        get_random_bytes(scratchpad, 16);

        sk.tfm = skcipher;
        sk.req = req;

        /* We encrypt one block */
        sg_init_one(&sk.sg, scratchpad, 16);
        skcipher_request_set_crypt(req, &sk.sg, &sk.sg, 16, ivdata);
        crypto_init_wait(&sk.wait);

        /* encrypt data */
        ret = test_skcipher_encdec(&sk, 1);
        if (ret)
            goto out;

        pr_info("Encryption triggered successfully\n");

            pr_debug("Encryption was successful\n");
    out:
        if (skcipher)
            crypto_free_skcipher(skcipher);
        if (req)
            crypto_free_skcipher(tfm);
            skcipher_request_free(req);
        if (ivdata)
            kfree(ivdata);
        if (scratchpad)
            kfree(scratchpad);
        return ret;
            kfree(data);
            return err;
    }


+1 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ Block Cipher Algorithm Definitions
   :doc: Block Cipher Algorithm Definitions

.. kernel-doc:: include/linux/crypto.h
   :functions: crypto_alg ablkcipher_alg blkcipher_alg cipher_alg
   :functions: crypto_alg ablkcipher_alg blkcipher_alg cipher_alg compress_alg

Symmetric Key Cipher API
------------------------
+1 −3
Original line number Diff line number Diff line
@@ -208,9 +208,7 @@ the aforementioned cipher types:
-  CRYPTO_ALG_TYPE_KPP Key-agreement Protocol Primitive (KPP) such as
   an ECDH or DH implementation

-  CRYPTO_ALG_TYPE_DIGEST Raw message digest

-  CRYPTO_ALG_TYPE_HASH Alias for CRYPTO_ALG_TYPE_DIGEST
-  CRYPTO_ALG_TYPE_HASH Raw message digest

-  CRYPTO_ALG_TYPE_SHASH Synchronous multi-block hash

+73 −38
Original line number Diff line number Diff line
=============
CRYPTO ENGINE
.. SPDX-License-Identifier: GPL-2.0
Crypto Engine
=============

Overview
--------
The crypto engine API (CE), is a crypto queue manager.
The crypto engine (CE) API is a crypto queue manager.

Requirement
-----------
You have to put at start of your tfm_ctx the struct crypto_engine_ctx::
You must put, at the start of your transform context your_tfm_ctx, the structure
crypto_engine:

::

	struct your_tfm_ctx {
        struct crypto_engine_ctx enginectx;
		struct crypto_engine engine;
		...
	};

Why: Since CE manage only crypto_async_request, it cannot know the underlying
request_type and so have access only on the TFM.
So using container_of for accessing __ctx is impossible.
Furthermore, the crypto engine cannot know the "struct your_tfm_ctx",
so it must assume that crypto_engine_ctx is at start of it.
The crypto engine only manages asynchronous requests in the form of
crypto_async_request. It cannot know the underlying request type and thus only
has access to the transform structure. It is not possible to access the context
using container_of. In addition, the engine knows nothing about your
structure "``struct your_tfm_ctx``". The engine assumes (requires) the placement
of the known member ``struct crypto_engine`` at the beginning.

Order of operations
-------------------
You have to obtain a struct crypto_engine via crypto_engine_alloc_init().
And start it via crypto_engine_start().
You are required to obtain a struct crypto_engine via ``crypto_engine_alloc_init()``.
Start it via ``crypto_engine_start()``. When finished with your work, shut down the
engine using ``crypto_engine_stop()`` and destroy the engine with
``crypto_engine_exit()``.

Before transferring any request, you have to fill the context enginectx by
providing functions for the following:

* ``prepare_crypt_hardware``: Called once before any prepare functions are
  called.

* ``unprepare_crypt_hardware``: Called once after all unprepare functions have
  been called.

Before transferring any request, you have to fill the enginectx.
- prepare_request: (taking a function pointer) If you need to do some processing before doing the request
- unprepare_request: (taking a function pointer) Undoing what's done in prepare_request
- do_one_request: (taking a function pointer) Do encryption for current request
* ``prepare_cipher_request``/``prepare_hash_request``: Called before each
  corresponding request is performed. If some processing or other preparatory
  work is required, do it here.

Note: that those three functions get the crypto_async_request associated with the received request.
So your need to get the original request via container_of(areq, struct yourrequesttype_request, base);
* ``unprepare_cipher_request``/``unprepare_hash_request``: Called after each
  request is handled. Clean up / undo what was done in the prepare function.

When your driver receive a crypto_request, you have to transfer it to
* ``cipher_one_request``/``hash_one_request``: Handle the current request by
  performing the operation.

Note that these functions access the crypto_async_request structure
associated with the received request. You are able to retrieve the original
request by using:

::

	container_of(areq, struct yourrequesttype_request, base);

When your driver receives a crypto_request, you must to transfer it to
the crypto engine via one of:
- crypto_transfer_ablkcipher_request_to_engine()
- crypto_transfer_aead_request_to_engine()
- crypto_transfer_akcipher_request_to_engine()
- crypto_transfer_hash_request_to_engine()
- crypto_transfer_skcipher_request_to_engine()

At the end of the request process, a call to one of the following function is needed:
- crypto_finalize_ablkcipher_request
- crypto_finalize_aead_request
- crypto_finalize_akcipher_request
- crypto_finalize_hash_request
- crypto_finalize_skcipher_request

* crypto_transfer_ablkcipher_request_to_engine()

* crypto_transfer_aead_request_to_engine()

* crypto_transfer_akcipher_request_to_engine()

* crypto_transfer_hash_request_to_engine()

* crypto_transfer_skcipher_request_to_engine()

At the end of the request process, a call to one of the following functions is needed:

* crypto_finalize_ablkcipher_request()

* crypto_finalize_aead_request()

* crypto_finalize_akcipher_request()

* crypto_finalize_hash_request()

* crypto_finalize_skcipher_request()
+0 −13
Original line number Diff line number Diff line
@@ -66,16 +66,3 @@ sha@f8034000 {
	dmas = <&dma1 2 17>;
	dma-names = "tx";
};

* Eliptic Curve Cryptography (I2C)

Required properties:
- compatible : must be "atmel,atecc508a".
- reg: I2C bus address of the device.
- clock-frequency: must be present in the i2c controller node.

Example:
atecc508a@c0 {
	compatible = "atmel,atecc508a";
	reg = <0xC0>;
};
Loading