diff options
| author | Jussi Kivilinna <jussi.kivilinna@mbnet.fi> | 2011-10-18 00:02:58 +0300 | 
|---|---|---|
| committer | Herbert Xu <herbert@gondor.apana.org.au> | 2011-11-09 11:42:59 +0800 | 
| commit | 3f3baf359dd3cc56fbaf9a2fb1a425ce7c18dbff (patch) | |
| tree | 735dc01ad32c9a76f37fe7adfb4ba880f13d7147 | |
| parent | 9d25917d49d986c417c173bfde50f41f96c5b202 (diff) | |
| download | olio-linux-3.10-3f3baf359dd3cc56fbaf9a2fb1a425ce7c18dbff.tar.xz olio-linux-3.10-3f3baf359dd3cc56fbaf9a2fb1a425ce7c18dbff.zip  | |
crypto: tcrypt - add test_acipher_speed
Add test_acipher_speed for testing async block ciphers.
Also include tests for aes/des/des3/ede as these appear to have ablk_cipher
implementations available.
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
| -rw-r--r-- | crypto/tcrypt.c | 250 | 
1 files changed, 250 insertions, 0 deletions
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index ac9e4d2a63b..dd3a0f8a091 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -719,6 +719,207 @@ out:  	crypto_free_ahash(tfm);  } +static inline int do_one_acipher_op(struct ablkcipher_request *req, int ret) +{ +	if (ret == -EINPROGRESS || ret == -EBUSY) { +		struct tcrypt_result *tr = req->base.data; + +		ret = wait_for_completion_interruptible(&tr->completion); +		if (!ret) +			ret = tr->err; +		INIT_COMPLETION(tr->completion); +	} + +	return ret; +} + +static int test_acipher_jiffies(struct ablkcipher_request *req, int enc, +				int blen, int sec) +{ +	unsigned long start, end; +	int bcount; +	int ret; + +	for (start = jiffies, end = start + sec * HZ, bcount = 0; +	     time_before(jiffies, end); bcount++) { +		if (enc) +			ret = do_one_acipher_op(req, +						crypto_ablkcipher_encrypt(req)); +		else +			ret = do_one_acipher_op(req, +						crypto_ablkcipher_decrypt(req)); + +		if (ret) +			return ret; +	} + +	pr_cont("%d operations in %d seconds (%ld bytes)\n", +		bcount, sec, (long)bcount * blen); +	return 0; +} + +static int test_acipher_cycles(struct ablkcipher_request *req, int enc, +			       int blen) +{ +	unsigned long cycles = 0; +	int ret = 0; +	int i; + +	/* Warm-up run. */ +	for (i = 0; i < 4; i++) { +		if (enc) +			ret = do_one_acipher_op(req, +						crypto_ablkcipher_encrypt(req)); +		else +			ret = do_one_acipher_op(req, +						crypto_ablkcipher_decrypt(req)); + +		if (ret) +			goto out; +	} + +	/* The real thing. */ +	for (i = 0; i < 8; i++) { +		cycles_t start, end; + +		start = get_cycles(); +		if (enc) +			ret = do_one_acipher_op(req, +						crypto_ablkcipher_encrypt(req)); +		else +			ret = do_one_acipher_op(req, +						crypto_ablkcipher_decrypt(req)); +		end = get_cycles(); + +		if (ret) +			goto out; + +		cycles += end - start; +	} + +out: +	if (ret == 0) +		pr_cont("1 operation in %lu cycles (%d bytes)\n", +			(cycles + 4) / 8, blen); + +	return ret; +} + +static void test_acipher_speed(const char *algo, int enc, unsigned int sec, +			       struct cipher_speed_template *template, +			       unsigned int tcount, u8 *keysize) +{ +	unsigned int ret, i, j, iv_len; +	struct tcrypt_result tresult; +	const char *key; +	char iv[128]; +	struct ablkcipher_request *req; +	struct crypto_ablkcipher *tfm; +	const char *e; +	u32 *b_size; + +	if (enc == ENCRYPT) +		e = "encryption"; +	else +		e = "decryption"; + +	pr_info("\ntesting speed of async %s %s\n", algo, e); + +	init_completion(&tresult.completion); + +	tfm = crypto_alloc_ablkcipher(algo, 0, 0); + +	if (IS_ERR(tfm)) { +		pr_err("failed to load transform for %s: %ld\n", algo, +		       PTR_ERR(tfm)); +		return; +	} + +	req = ablkcipher_request_alloc(tfm, GFP_KERNEL); +	if (!req) { +		pr_err("tcrypt: skcipher: Failed to allocate request for %s\n", +		       algo); +		goto out; +	} + +	ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, +					tcrypt_complete, &tresult); + +	i = 0; +	do { +		b_size = block_sizes; + +		do { +			struct scatterlist sg[TVMEMSIZE]; + +			if ((*keysize + *b_size) > TVMEMSIZE * PAGE_SIZE) { +				pr_err("template (%u) too big for " +				       "tvmem (%lu)\n", *keysize + *b_size, +				       TVMEMSIZE * PAGE_SIZE); +				goto out_free_req; +			} + +			pr_info("test %u (%d bit key, %d byte blocks): ", i, +				*keysize * 8, *b_size); + +			memset(tvmem[0], 0xff, PAGE_SIZE); + +			/* set key, plain text and IV */ +			key = tvmem[0]; +			for (j = 0; j < tcount; j++) { +				if (template[j].klen == *keysize) { +					key = template[j].key; +					break; +				} +			} + +			crypto_ablkcipher_clear_flags(tfm, ~0); + +			ret = crypto_ablkcipher_setkey(tfm, key, *keysize); +			if (ret) { +				pr_err("setkey() failed flags=%x\n", +					crypto_ablkcipher_get_flags(tfm)); +				goto out_free_req; +			} + +			sg_init_table(sg, TVMEMSIZE); +			sg_set_buf(sg, tvmem[0] + *keysize, +				   PAGE_SIZE - *keysize); +			for (j = 1; j < TVMEMSIZE; j++) { +				sg_set_buf(sg + j, tvmem[j], PAGE_SIZE); +				memset(tvmem[j], 0xff, PAGE_SIZE); +			} + +			iv_len = crypto_ablkcipher_ivsize(tfm); +			if (iv_len) +				memset(&iv, 0xff, iv_len); + +			ablkcipher_request_set_crypt(req, sg, sg, *b_size, iv); + +			if (sec) +				ret = test_acipher_jiffies(req, enc, +							   *b_size, sec); +			else +				ret = test_acipher_cycles(req, enc, +							  *b_size); + +			if (ret) { +				pr_err("%s() failed flags=%x\n", e, +					crypto_ablkcipher_get_flags(tfm)); +				break; +			} +			b_size++; +			i++; +		} while (*b_size); +		keysize++; +	} while (*keysize); + +out_free_req: +	ablkcipher_request_free(req); +out: +	crypto_free_ablkcipher(tfm); +} +  static void test_available(void)  {  	char **name = check; @@ -1243,6 +1444,55 @@ static int do_test(int m)  	case 499:  		break; +	case 500: +		test_acipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0, +				   speed_template_16_24_32); +		test_acipher_speed("ecb(aes)", DECRYPT, sec, NULL, 0, +				   speed_template_16_24_32); +		test_acipher_speed("cbc(aes)", ENCRYPT, sec, NULL, 0, +				   speed_template_16_24_32); +		test_acipher_speed("cbc(aes)", DECRYPT, sec, NULL, 0, +				   speed_template_16_24_32); +		test_acipher_speed("lrw(aes)", ENCRYPT, sec, NULL, 0, +				   speed_template_32_40_48); +		test_acipher_speed("lrw(aes)", DECRYPT, sec, NULL, 0, +				   speed_template_32_40_48); +		test_acipher_speed("xts(aes)", ENCRYPT, sec, NULL, 0, +				   speed_template_32_48_64); +		test_acipher_speed("xts(aes)", DECRYPT, sec, NULL, 0, +				   speed_template_32_48_64); +		test_acipher_speed("ctr(aes)", ENCRYPT, sec, NULL, 0, +				   speed_template_16_24_32); +		test_acipher_speed("ctr(aes)", DECRYPT, sec, NULL, 0, +				   speed_template_16_24_32); +		break; + +	case 501: +		test_acipher_speed("ecb(des3_ede)", ENCRYPT, sec, +				   des3_speed_template, DES3_SPEED_VECTORS, +				   speed_template_24); +		test_acipher_speed("ecb(des3_ede)", DECRYPT, sec, +				   des3_speed_template, DES3_SPEED_VECTORS, +				   speed_template_24); +		test_acipher_speed("cbc(des3_ede)", ENCRYPT, sec, +				   des3_speed_template, DES3_SPEED_VECTORS, +				   speed_template_24); +		test_acipher_speed("cbc(des3_ede)", DECRYPT, sec, +				   des3_speed_template, DES3_SPEED_VECTORS, +				   speed_template_24); +		break; + +	case 502: +		test_acipher_speed("ecb(des)", ENCRYPT, sec, NULL, 0, +				   speed_template_8); +		test_acipher_speed("ecb(des)", DECRYPT, sec, NULL, 0, +				   speed_template_8); +		test_acipher_speed("cbc(des)", ENCRYPT, sec, NULL, 0, +				   speed_template_8); +		test_acipher_speed("cbc(des)", DECRYPT, sec, NULL, 0, +				   speed_template_8); +		break; +  	case 1000:  		test_available();  		break;  |