brintos

brintos / linux-shallow public Read only

0
0
Text · 8.4 KiB · 8141d45 Raw
370 lines · c
1/* SPDX-License-Identifier: GPL-2.02 *3 * Copyright (C) 2022 Red Hat, Inc.4 * Author: Vladis Dronov <vdronoff@gmail.com>5 */6 7#include <asm/elf.h>8#include <asm/uaccess.h>9#include <asm/smp.h>10#include <crypto/skcipher.h>11#include <crypto/akcipher.h>12#include <crypto/acompress.h>13#include <crypto/rng.h>14#include <crypto/drbg.h>15#include <crypto/kpp.h>16#include <crypto/internal/simd.h>17#include <crypto/chacha.h>18#include <crypto/aead.h>19#include <crypto/hash.h>20#include <linux/crypto.h>21#include <linux/debugfs.h>22#include <linux/delay.h>23#include <linux/err.h>24#include <linux/fs.h>25#include <linux/fips.h>26#include <linux/kernel.h>27#include <linux/kthread.h>28#include <linux/module.h>29#include <linux/sched.h>30#include <linux/scatterlist.h>31#include <linux/time.h>32#include <linux/vmalloc.h>33#include <linux/zlib.h>34#include <linux/once.h>35#include <linux/random.h>36#include <linux/slab.h>37#include <linux/string.h>38 39static unsigned int data_size __read_mostly = 256;40static unsigned int debug __read_mostly = 0;41 42/* tie all skcipher structures together */43struct skcipher_def {44	struct scatterlist sginp, sgout;45	struct crypto_skcipher *tfm;46	struct skcipher_request *req;47	struct crypto_wait wait;48};49 50/* Perform cipher operations with the chacha lib */51static int test_lib_chacha(u8 *revert, u8 *cipher, u8 *plain)52{53	u32 chacha_state[CHACHA_STATE_WORDS];54	u8 iv[16], key[32];55	u64 start, end;56 57	memset(key, 'X', sizeof(key));58	memset(iv, 'I', sizeof(iv));59 60	if (debug) {61		print_hex_dump(KERN_INFO, "key: ", DUMP_PREFIX_OFFSET,62			       16, 1, key, 32, 1);63 64		print_hex_dump(KERN_INFO, "iv:  ", DUMP_PREFIX_OFFSET,65			       16, 1, iv, 16, 1);66	}67 68	/* Encrypt */69	chacha_init_arch(chacha_state, (u32*)key, iv);70 71	start = ktime_get_ns();72	chacha_crypt_arch(chacha_state, cipher, plain, data_size, 20);73	end = ktime_get_ns();74 75 76	if (debug)77		print_hex_dump(KERN_INFO, "encr:", DUMP_PREFIX_OFFSET,78			       16, 1, cipher,79			       (data_size > 64 ? 64 : data_size), 1);80 81	pr_info("lib encryption took: %lld nsec", end - start);82 83	/* Decrypt */84	chacha_init_arch(chacha_state, (u32 *)key, iv);85 86	start = ktime_get_ns();87	chacha_crypt_arch(chacha_state, revert, cipher, data_size, 20);88	end = ktime_get_ns();89 90	if (debug)91		print_hex_dump(KERN_INFO, "decr:", DUMP_PREFIX_OFFSET,92			       16, 1, revert,93			       (data_size > 64 ? 64 : data_size), 1);94 95	pr_info("lib decryption took: %lld nsec", end - start);96 97	return 0;98}99 100/* Perform cipher operations with skcipher */101static unsigned int test_skcipher_encdec(struct skcipher_def *sk,102					 int enc)103{104	int rc;105 106	if (enc) {107		rc = crypto_wait_req(crypto_skcipher_encrypt(sk->req),108				     &sk->wait);109		if (rc)110			pr_info("skcipher encrypt returned with result"111				"%d\n", rc);112	}113	else114	{115		rc = crypto_wait_req(crypto_skcipher_decrypt(sk->req),116				     &sk->wait);117		if (rc)118			pr_info("skcipher decrypt returned with result"119				"%d\n", rc);120	}121 122	return rc;123}124 125/* Initialize and trigger cipher operations */126static int test_skcipher(char *name, u8 *revert, u8 *cipher, u8 *plain)127{128	struct skcipher_def sk;129	struct crypto_skcipher *skcipher = NULL;130	struct skcipher_request *req = NULL;131	u8 iv[16], key[32];132	u64 start, end;133	int ret = -EFAULT;134 135	skcipher = crypto_alloc_skcipher(name, 0, 0);136	if (IS_ERR(skcipher)) {137		pr_info("could not allocate skcipher %s handle\n", name);138		return PTR_ERR(skcipher);139	}140 141	req = skcipher_request_alloc(skcipher, GFP_KERNEL);142	if (!req) {143		pr_info("could not allocate skcipher request\n");144		ret = -ENOMEM;145		goto out;146	}147 148	skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,149					  crypto_req_done,150					  &sk.wait);151 152	memset(key, 'X', sizeof(key));153	memset(iv, 'I', sizeof(iv));154 155	if (crypto_skcipher_setkey(skcipher, key, 32)) {156		pr_info("key could not be set\n");157		ret = -EAGAIN;158		goto out;159	}160 161	if (debug) {162		print_hex_dump(KERN_INFO, "key: ", DUMP_PREFIX_OFFSET,163			       16, 1, key, 32, 1);164 165		print_hex_dump(KERN_INFO, "iv:  ", DUMP_PREFIX_OFFSET,166			       16, 1, iv, 16, 1);167	}168 169	sk.tfm = skcipher;170	sk.req = req;171 172	/* Encrypt in one pass */173	sg_init_one(&sk.sginp, plain, data_size);174	sg_init_one(&sk.sgout, cipher, data_size);175	skcipher_request_set_crypt(req, &sk.sginp, &sk.sgout,176				   data_size, iv);177	crypto_init_wait(&sk.wait);178 179	/* Encrypt data */180	start = ktime_get_ns();181	ret = test_skcipher_encdec(&sk, 1);182	end = ktime_get_ns();183 184	if (ret)185		goto out;186 187	pr_info("%s tfm encryption successful, took %lld nsec\n", name, end - start);188 189	if (debug)190		print_hex_dump(KERN_INFO, "encr:", DUMP_PREFIX_OFFSET,191			       16, 1, cipher,192			       (data_size > 64 ? 64 : data_size), 1);193 194	/* Prepare for decryption */195	memset(iv, 'I', sizeof(iv));196 197	sg_init_one(&sk.sginp, cipher, data_size);198	sg_init_one(&sk.sgout, revert, data_size);199	skcipher_request_set_crypt(req, &sk.sginp, &sk.sgout,200				   data_size, iv);201	crypto_init_wait(&sk.wait);202 203	/* Decrypt data */204	start = ktime_get_ns();205	ret = test_skcipher_encdec(&sk, 0);206	end = ktime_get_ns();207 208	if (ret)209		goto out;210 211	pr_info("%s tfm decryption successful, took %lld nsec\n", name, end - start);212 213	if (debug)214		print_hex_dump(KERN_INFO, "decr:", DUMP_PREFIX_OFFSET,215			       16, 1, revert,216			       (data_size > 64 ? 64 : data_size), 1);217 218	/* Dump some internal skcipher data */219	if (debug)220		pr_info("skcipher %s: cryptlen %d blksize %d stride %d "221			"ivsize %d alignmask 0x%x\n",222			name, sk.req->cryptlen,223			crypto_skcipher_blocksize(sk.tfm),224			crypto_skcipher_alg(sk.tfm)->walksize,225			crypto_skcipher_ivsize(sk.tfm),226			crypto_skcipher_alignmask(sk.tfm));227 228out:229	if (skcipher)230		crypto_free_skcipher(skcipher);231	if (req)232		skcipher_request_free(req);233	return ret;234}235 236static int __init chacha_s390_test_init(void)237{238	u8 *plain = NULL, *revert = NULL;239	u8 *cipher_generic = NULL, *cipher_s390 = NULL;240	int ret = -1;241 242	pr_info("s390 ChaCha20 test module: size=%d debug=%d\n",243		data_size, debug);244 245	/* Allocate and fill buffers */246	plain = vmalloc(data_size);247	if (!plain) {248		pr_info("could not allocate plain buffer\n");249		ret = -2;250		goto out;251	}252	memset(plain, 'a', data_size);253	get_random_bytes(plain, (data_size > 256 ? 256 : data_size));254 255	cipher_generic = vzalloc(data_size);256	if (!cipher_generic) {257		pr_info("could not allocate cipher_generic buffer\n");258		ret = -2;259		goto out;260	}261 262	cipher_s390 = vzalloc(data_size);263	if (!cipher_s390) {264		pr_info("could not allocate cipher_s390 buffer\n");265		ret = -2;266		goto out;267	}268 269	revert = vzalloc(data_size);270	if (!revert) {271		pr_info("could not allocate revert buffer\n");272		ret = -2;273		goto out;274	}275 276	if (debug)277		print_hex_dump(KERN_INFO, "src: ", DUMP_PREFIX_OFFSET,278			       16, 1, plain,279			       (data_size > 64 ? 64 : data_size), 1);280 281	/* Use chacha20 generic */282	ret = test_skcipher("chacha20-generic", revert, cipher_generic, plain);283	if (ret)284		goto out;285 286	if (memcmp(plain, revert, data_size)) {287		pr_info("generic en/decryption check FAILED\n");288		ret = -2;289		goto out;290	}291	else292		pr_info("generic en/decryption check OK\n");293 294	memset(revert, 0, data_size);295 296	/* Use chacha20 s390 */297	ret = test_skcipher("chacha20-s390", revert, cipher_s390, plain);298	if (ret)299		goto out;300 301	if (memcmp(plain, revert, data_size)) {302		pr_info("s390 en/decryption check FAILED\n");303		ret = -2;304		goto out;305	}306	else307		pr_info("s390 en/decryption check OK\n");308 309	if (memcmp(cipher_generic, cipher_s390, data_size)) {310		pr_info("s390 vs generic check FAILED\n");311		ret = -2;312		goto out;313	}314	else315		pr_info("s390 vs generic check OK\n");316 317	memset(cipher_s390, 0, data_size);318	memset(revert, 0, data_size);319 320	/* Use chacha20 lib */321	test_lib_chacha(revert, cipher_s390, plain);322 323	if (memcmp(plain, revert, data_size)) {324		pr_info("lib en/decryption check FAILED\n");325		ret = -2;326		goto out;327	}328	else329		pr_info("lib en/decryption check OK\n");330 331	if (memcmp(cipher_generic, cipher_s390, data_size)) {332		pr_info("lib vs generic check FAILED\n");333		ret = -2;334		goto out;335	}336	else337		pr_info("lib vs generic check OK\n");338 339	pr_info("--- chacha20 s390 test end ---\n");340 341out:342	if (plain)343		vfree(plain);344	if (cipher_generic)345		vfree(cipher_generic);346	if (cipher_s390)347		vfree(cipher_s390);348	if (revert)349		vfree(revert);350 351	return -1;352}353 354static void __exit chacha_s390_test_exit(void)355{356	pr_info("s390 ChaCha20 test module exit\n");357}358 359module_param_named(size, data_size, uint, 0660);360module_param(debug, int, 0660);361MODULE_PARM_DESC(size, "Size of a plaintext");362MODULE_PARM_DESC(debug, "Debug level (0=off,1=on)");363 364module_init(chacha_s390_test_init);365module_exit(chacha_s390_test_exit);366 367MODULE_DESCRIPTION("s390 ChaCha20 self-test");368MODULE_AUTHOR("Vladis Dronov <vdronoff@gmail.com>");369MODULE_LICENSE("GPL v2");370