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