162306a36Sopenharmony_ciCode Examples
262306a36Sopenharmony_ci=============
362306a36Sopenharmony_ci
462306a36Sopenharmony_ciCode Example For Symmetric Key Cipher Operation
562306a36Sopenharmony_ci-----------------------------------------------
662306a36Sopenharmony_ci
762306a36Sopenharmony_ciThis code encrypts some data with AES-256-XTS.  For sake of example,
862306a36Sopenharmony_ciall inputs are random bytes, the encryption is done in-place, and it's
962306a36Sopenharmony_ciassumed the code is running in a context where it can sleep.
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci::
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci    static int test_skcipher(void)
1462306a36Sopenharmony_ci    {
1562306a36Sopenharmony_ci            struct crypto_skcipher *tfm = NULL;
1662306a36Sopenharmony_ci            struct skcipher_request *req = NULL;
1762306a36Sopenharmony_ci            u8 *data = NULL;
1862306a36Sopenharmony_ci            const size_t datasize = 512; /* data size in bytes */
1962306a36Sopenharmony_ci            struct scatterlist sg;
2062306a36Sopenharmony_ci            DECLARE_CRYPTO_WAIT(wait);
2162306a36Sopenharmony_ci            u8 iv[16];  /* AES-256-XTS takes a 16-byte IV */
2262306a36Sopenharmony_ci            u8 key[64]; /* AES-256-XTS takes a 64-byte key */
2362306a36Sopenharmony_ci            int err;
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci            /*
2662306a36Sopenharmony_ci             * Allocate a tfm (a transformation object) and set the key.
2762306a36Sopenharmony_ci             *
2862306a36Sopenharmony_ci             * In real-world use, a tfm and key are typically used for many
2962306a36Sopenharmony_ci             * encryption/decryption operations.  But in this example, we'll just do a
3062306a36Sopenharmony_ci             * single encryption operation with it (which is not very efficient).
3162306a36Sopenharmony_ci             */
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci            tfm = crypto_alloc_skcipher("xts(aes)", 0, 0);
3462306a36Sopenharmony_ci            if (IS_ERR(tfm)) {
3562306a36Sopenharmony_ci                    pr_err("Error allocating xts(aes) handle: %ld\n", PTR_ERR(tfm));
3662306a36Sopenharmony_ci                    return PTR_ERR(tfm);
3762306a36Sopenharmony_ci            }
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci            get_random_bytes(key, sizeof(key));
4062306a36Sopenharmony_ci            err = crypto_skcipher_setkey(tfm, key, sizeof(key));
4162306a36Sopenharmony_ci            if (err) {
4262306a36Sopenharmony_ci                    pr_err("Error setting key: %d\n", err);
4362306a36Sopenharmony_ci                    goto out;
4462306a36Sopenharmony_ci            }
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci            /* Allocate a request object */
4762306a36Sopenharmony_ci            req = skcipher_request_alloc(tfm, GFP_KERNEL);
4862306a36Sopenharmony_ci            if (!req) {
4962306a36Sopenharmony_ci                    err = -ENOMEM;
5062306a36Sopenharmony_ci                    goto out;
5162306a36Sopenharmony_ci            }
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci            /* Prepare the input data */
5462306a36Sopenharmony_ci            data = kmalloc(datasize, GFP_KERNEL);
5562306a36Sopenharmony_ci            if (!data) {
5662306a36Sopenharmony_ci                    err = -ENOMEM;
5762306a36Sopenharmony_ci                    goto out;
5862306a36Sopenharmony_ci            }
5962306a36Sopenharmony_ci            get_random_bytes(data, datasize);
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci            /* Initialize the IV */
6262306a36Sopenharmony_ci            get_random_bytes(iv, sizeof(iv));
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci            /*
6562306a36Sopenharmony_ci             * Encrypt the data in-place.
6662306a36Sopenharmony_ci             *
6762306a36Sopenharmony_ci             * For simplicity, in this example we wait for the request to complete
6862306a36Sopenharmony_ci             * before proceeding, even if the underlying implementation is asynchronous.
6962306a36Sopenharmony_ci             *
7062306a36Sopenharmony_ci             * To decrypt instead of encrypt, just change crypto_skcipher_encrypt() to
7162306a36Sopenharmony_ci             * crypto_skcipher_decrypt().
7262306a36Sopenharmony_ci             */
7362306a36Sopenharmony_ci            sg_init_one(&sg, data, datasize);
7462306a36Sopenharmony_ci            skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
7562306a36Sopenharmony_ci                                               CRYPTO_TFM_REQ_MAY_SLEEP,
7662306a36Sopenharmony_ci                                          crypto_req_done, &wait);
7762306a36Sopenharmony_ci            skcipher_request_set_crypt(req, &sg, &sg, datasize, iv);
7862306a36Sopenharmony_ci            err = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
7962306a36Sopenharmony_ci            if (err) {
8062306a36Sopenharmony_ci                    pr_err("Error encrypting data: %d\n", err);
8162306a36Sopenharmony_ci                    goto out;
8262306a36Sopenharmony_ci            }
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci            pr_debug("Encryption was successful\n");
8562306a36Sopenharmony_ci    out:
8662306a36Sopenharmony_ci            crypto_free_skcipher(tfm);
8762306a36Sopenharmony_ci            skcipher_request_free(req);
8862306a36Sopenharmony_ci            kfree(data);
8962306a36Sopenharmony_ci            return err;
9062306a36Sopenharmony_ci    }
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ciCode Example For Use of Operational State Memory With SHASH
9462306a36Sopenharmony_ci-----------------------------------------------------------
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci::
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci    struct sdesc {
10062306a36Sopenharmony_ci        struct shash_desc shash;
10162306a36Sopenharmony_ci        char ctx[];
10262306a36Sopenharmony_ci    };
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci    static struct sdesc *init_sdesc(struct crypto_shash *alg)
10562306a36Sopenharmony_ci    {
10662306a36Sopenharmony_ci        struct sdesc *sdesc;
10762306a36Sopenharmony_ci        int size;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci        size = sizeof(struct shash_desc) + crypto_shash_descsize(alg);
11062306a36Sopenharmony_ci        sdesc = kmalloc(size, GFP_KERNEL);
11162306a36Sopenharmony_ci        if (!sdesc)
11262306a36Sopenharmony_ci            return ERR_PTR(-ENOMEM);
11362306a36Sopenharmony_ci        sdesc->shash.tfm = alg;
11462306a36Sopenharmony_ci        return sdesc;
11562306a36Sopenharmony_ci    }
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci    static int calc_hash(struct crypto_shash *alg,
11862306a36Sopenharmony_ci                 const unsigned char *data, unsigned int datalen,
11962306a36Sopenharmony_ci                 unsigned char *digest)
12062306a36Sopenharmony_ci    {
12162306a36Sopenharmony_ci        struct sdesc *sdesc;
12262306a36Sopenharmony_ci        int ret;
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci        sdesc = init_sdesc(alg);
12562306a36Sopenharmony_ci        if (IS_ERR(sdesc)) {
12662306a36Sopenharmony_ci            pr_info("can't alloc sdesc\n");
12762306a36Sopenharmony_ci            return PTR_ERR(sdesc);
12862306a36Sopenharmony_ci        }
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci        ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest);
13162306a36Sopenharmony_ci        kfree(sdesc);
13262306a36Sopenharmony_ci        return ret;
13362306a36Sopenharmony_ci    }
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci    static int test_hash(const unsigned char *data, unsigned int datalen,
13662306a36Sopenharmony_ci                 unsigned char *digest)
13762306a36Sopenharmony_ci    {
13862306a36Sopenharmony_ci        struct crypto_shash *alg;
13962306a36Sopenharmony_ci        char *hash_alg_name = "sha1-padlock-nano";
14062306a36Sopenharmony_ci        int ret;
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci        alg = crypto_alloc_shash(hash_alg_name, 0, 0);
14362306a36Sopenharmony_ci        if (IS_ERR(alg)) {
14462306a36Sopenharmony_ci                pr_info("can't alloc alg %s\n", hash_alg_name);
14562306a36Sopenharmony_ci                return PTR_ERR(alg);
14662306a36Sopenharmony_ci        }
14762306a36Sopenharmony_ci        ret = calc_hash(alg, data, datalen, digest);
14862306a36Sopenharmony_ci        crypto_free_shash(alg);
14962306a36Sopenharmony_ci        return ret;
15062306a36Sopenharmony_ci    }
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ciCode Example For Random Number Generator Usage
15462306a36Sopenharmony_ci----------------------------------------------
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci::
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci    static int get_random_numbers(u8 *buf, unsigned int len)
16062306a36Sopenharmony_ci    {
16162306a36Sopenharmony_ci        struct crypto_rng *rng = NULL;
16262306a36Sopenharmony_ci        char *drbg = "drbg_nopr_sha256"; /* Hash DRBG with SHA-256, no PR */
16362306a36Sopenharmony_ci        int ret;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci        if (!buf || !len) {
16662306a36Sopenharmony_ci            pr_debug("No output buffer provided\n");
16762306a36Sopenharmony_ci            return -EINVAL;
16862306a36Sopenharmony_ci        }
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci        rng = crypto_alloc_rng(drbg, 0, 0);
17162306a36Sopenharmony_ci        if (IS_ERR(rng)) {
17262306a36Sopenharmony_ci            pr_debug("could not allocate RNG handle for %s\n", drbg);
17362306a36Sopenharmony_ci            return PTR_ERR(rng);
17462306a36Sopenharmony_ci        }
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci        ret = crypto_rng_get_bytes(rng, buf, len);
17762306a36Sopenharmony_ci        if (ret < 0)
17862306a36Sopenharmony_ci            pr_debug("generation of random numbers failed\n");
17962306a36Sopenharmony_ci        else if (ret == 0)
18062306a36Sopenharmony_ci            pr_debug("RNG returned no data");
18162306a36Sopenharmony_ci        else
18262306a36Sopenharmony_ci            pr_debug("RNG returned %d bytes of data\n", ret);
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci    out:
18562306a36Sopenharmony_ci        crypto_free_rng(rng);
18662306a36Sopenharmony_ci        return ret;
18762306a36Sopenharmony_ci    }
188