diff options
Diffstat (limited to 'Documentation/crypto/api-samples.rst')
-rw-r--r-- | Documentation/crypto/api-samples.rst | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/Documentation/crypto/api-samples.rst b/Documentation/crypto/api-samples.rst new file mode 100644 index 000000000000..0a10819f6107 --- /dev/null +++ b/Documentation/crypto/api-samples.rst @@ -0,0 +1,224 @@ +Code Examples +============= + +Code Example For Symmetric Key Cipher Operation +----------------------------------------------- + +:: + + + struct tcrypt_result { + struct completion completion; + int err; + }; + + /* tie all data structures together */ + struct skcipher_def { + struct scatterlist sg; + struct crypto_skcipher *tfm; + struct skcipher_request *req; + struct tcrypt_result result; + }; + + /* Callback function */ + static void test_skcipher_cb(struct crypto_async_request *req, int error) + { + struct tcrypt_result *result = req->data; + + if (error == -EINPROGRESS) + return; + result->err = error; + complete(&result->completion); + pr_info("Encryption finished successfully\n"); + } + + /* Perform cipher operation */ + static unsigned int test_skcipher_encdec(struct skcipher_def *sk, + int enc) + { + int rc = 0; + + if (enc) + rc = crypto_skcipher_encrypt(sk->req); + else + rc = crypto_skcipher_decrypt(sk->req); + + switch (rc) { + case 0: + break; + case -EINPROGRESS: + case -EBUSY: + rc = wait_for_completion_interruptible( + &sk->result.completion); + if (!rc && !sk->result.err) { + reinit_completion(&sk->result.completion); + break; + } + default: + pr_info("skcipher encrypt returned with %d result %d\n", + rc, sk->result.err); + break; + } + init_completion(&sk->result.completion); + + return rc; + } + + /* Initialize and trigger cipher operation */ + static int test_skcipher(void) + { + struct skcipher_def sk; + struct crypto_skcipher *skcipher = 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); + } + + req = skcipher_request_alloc(skcipher, GFP_KERNEL); + if (!req) { + pr_info("could not allocate skcipher request\n"); + ret = -ENOMEM; + goto out; + } + + skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + test_skcipher_cb, + &sk.result); + + /* 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; + goto out; + } + + /* IV will be random */ + ivdata = kmalloc(16, GFP_KERNEL); + if (!ivdata) { + pr_info("could not allocate ivdata\n"); + 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"); + 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); + init_completion(&sk.result.completion); + + /* encrypt data */ + ret = test_skcipher_encdec(&sk, 1); + if (ret) + goto out; + + pr_info("Encryption triggered successfully\n"); + + out: + if (skcipher) + crypto_free_skcipher(skcipher); + if (req) + skcipher_request_free(req); + if (ivdata) + kfree(ivdata); + if (scratchpad) + kfree(scratchpad); + return ret; + } + + +Code Example For Use of Operational State Memory With SHASH +----------------------------------------------------------- + +:: + + + struct sdesc { + struct shash_desc shash; + char ctx[]; + }; + + static struct sdescinit_sdesc(struct crypto_shash *alg) + { + struct sdescsdesc; + int size; + + size = sizeof(struct shash_desc) + crypto_shash_descsize(alg); + sdesc = kmalloc(size, GFP_KERNEL); + if (!sdesc) + return ERR_PTR(-ENOMEM); + sdesc->shash.tfm = alg; + sdesc->shash.flags = 0x0; + return sdesc; + } + + static int calc_hash(struct crypto_shashalg, + const unsigned chardata, unsigned int datalen, + unsigned chardigest) { + struct sdescsdesc; + int ret; + + sdesc = init_sdesc(alg); + if (IS_ERR(sdesc)) { + pr_info("trusted_key: can't alloc %s\n", hash_alg); + return PTR_ERR(sdesc); + } + + ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest); + kfree(sdesc); + return ret; + } + + +Code Example For Random Number Generator Usage +---------------------------------------------- + +:: + + + static int get_random_numbers(u8 *buf, unsigned int len) + { + struct crypto_rngrng = NULL; + chardrbg = "drbg_nopr_sha256"; /* Hash DRBG with SHA-256, no PR */ + int ret; + + if (!buf || !len) { + pr_debug("No output buffer provided\n"); + return -EINVAL; + } + + rng = crypto_alloc_rng(drbg, 0, 0); + if (IS_ERR(rng)) { + pr_debug("could not allocate RNG handle for %s\n", drbg); + return -PTR_ERR(rng); + } + + ret = crypto_rng_get_bytes(rng, buf, len); + if (ret < 0) + pr_debug("generation of random numbers failed\n"); + else if (ret == 0) + pr_debug("RNG returned no data"); + else + pr_debug("RNG returned %d bytes of data\n", ret); + + out: + crypto_free_rng(rng); + return ret; + } |