Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 561

kernel-2.6.18-238.el5.src.rpm

From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Wed, 27 Aug 2008 10:18:30 +1000
Subject: [CRYPTO] tcrypt: Avoid using contiguous pages
Message-id: E1KY8k2-0002Gy-00@gondolin.me.apana.org.au
O-Subject: [PATCH 8/19] crypto: tcrypt - Avoid using contiguous pages
Bugzilla: 446522

RHEL5 bugzilla #446522

crypto: tcrypt - Avoid using contiguous pages

If tcrypt is to be used as a run-time integrity test, it needs to be
more resilient in a hostile environment.  For a start allocating 32K
of physically contiguous memory is definitely out.

This patch teaches it to use separate pages instead.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 7e47e8d..1576c22 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -34,10 +34,10 @@
 #include "tcrypt.h"
 
 /*
- * Need to kmalloc() memory for testing.
+ * Need slab memory for testing (size in number of pages).
  */
-#define TVMEMSIZE	16384
-#define XBUFSIZE	32768
+#define TVMEMSIZE	4
+#define XBUFSIZE	8
 
 /*
  * Indexes into the xbuf to simulate cross-page access.
@@ -70,9 +70,9 @@ static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 };
 static unsigned int sec;
 
 static int mode;
-static char *xbuf;
-static char *axbuf;
-static char *tvmem;
+static char *xbuf[XBUFSIZE];
+static char *axbuf[XBUFSIZE];
+static char *tvmem[TVMEMSIZE];
 
 static char *check[] = {
 	"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
@@ -121,9 +121,7 @@ static void test_hash(char *algo, struct hash_testvec *template,
 		printk("test %u:\n", i + 1);
 		memset(result, 0, 64);
 
-		hash_buff = kzalloc(template[i].psize, GFP_KERNEL);
-		if (!hash_buff)
-			continue;
+		hash_buff = xbuf[0];
 
 		memcpy(hash_buff, template[i].plaintext, template[i].psize);
 		sg_init_one(&sg[0], hash_buff, template[i].psize);
@@ -141,14 +139,10 @@ static void test_hash(char *algo, struct hash_testvec *template,
 		       memcmp(result, template[i].digest,
 			      crypto_tfm_alg_digestsize(tfm)) ?
 		       "fail" : "pass");
-		kfree(hash_buff);
 	}
 
 	printk("testing %s across pages\n", algo);
 
-	/* setup the dummy buffer first */
-	memset(xbuf, 0, XBUFSIZE);
-
 	j = 0;
 	for (i = 0; i < tcount; i++) {
 		if (template[i].np) {
@@ -206,9 +200,7 @@ static void test_nhash(char *algo, struct hash_testvec *template,
 		printk("test %u:\n", i + 1);
 		memset(result, 0, 64);
 
-		hash_buff = kzalloc(template[i].psize, GFP_KERNEL);
-		if (!hash_buff)
-			continue;
+		hash_buff = xbuf[0];
 
 		memcpy(hash_buff, template[i].plaintext, template[i].psize);
 		sg_init_one(&sg[0], hash_buff, template[i].psize);
@@ -218,7 +210,6 @@ static void test_nhash(char *algo, struct hash_testvec *template,
 						 template[i].ksize);
 			if (ret) {
 				printk("setkey() failed ret=%d\n", ret);
-				kfree(hash_buff);
 				goto out;
 			}
 		}
@@ -226,7 +217,6 @@ static void test_nhash(char *algo, struct hash_testvec *template,
 		ret = crypto_hash_digest(&desc, sg, template[i].psize, result);
 		if (ret) {
 			printk("digest () failed ret=%d\n", ret);
-			kfree(hash_buff);
 			goto out;
 		}
 
@@ -235,14 +225,10 @@ static void test_nhash(char *algo, struct hash_testvec *template,
 		       memcmp(result, template[i].digest,
 			      crypto_hash_digestsize(tfm)) ?
 		       "fail" : "pass");
-		kfree(hash_buff);
 	}
 
 	printk("testing %s across pages\n", algo);
 
-	/* setup the dummy buffer first */
-	memset(xbuf, 0, XBUFSIZE);
-
 	j = 0;
 	for (i = 0; i < tcount; i++) {
 		if (template[i].np) {
@@ -253,12 +239,13 @@ static void test_nhash(char *algo, struct hash_testvec *template,
 			temp = 0;
 			sg_init_table(sg, template[i].np);
 			for (k = 0; k < template[i].np; k++) {
-				memcpy(&xbuf[IDX[k]],
-				       template[i].plaintext + temp,
-				       template[i].tap[k]);
+				sg_set_buf(&sg[k],
+					   memcpy(xbuf[IDX[k] >> PAGE_SHIFT] +
+						  offset_in_page(IDX[k]),
+						  template[i].plaintext + temp,
+						  template[i].tap[k]),
+					   template[i].tap[k]);
 				temp += template[i].tap[k];
-				sg_set_buf(&sg[k], &xbuf[IDX[k]],
-					    template[i].tap[k]);
 			}
 
 			if (template[i].ksize) {
@@ -341,15 +328,8 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
 			/* some tepmplates have no input data but they will
 			 * touch input
 			 */
-			input = kzalloc(template[i].ilen + template[i].rlen, GFP_KERNEL);
-			if (!input)
-				continue;
-
-			assoc = kzalloc(template[i].alen, GFP_KERNEL);
-			if (!assoc) {
-				kfree(input);
-				continue;
-			}
+			input = xbuf[0];
+			assoc = axbuf[0];
 
 			memcpy(input, template[i].input, template[i].ilen);
 			memcpy(assoc, template[i].assoc, template[i].alen);
@@ -363,10 +343,7 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
 				crypto_aead_set_flags(
 					tfm, CRYPTO_TFM_REQ_WEAK_KEY);
 
-			if (template[i].key)
-				key = template[i].key;
-			else
-				key = kzalloc(template[i].klen, GFP_KERNEL);
+			key = template[i].key;
 
 			ret = crypto_aead_setkey(tfm, key,
 						 template[i].klen);
@@ -375,7 +352,7 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
 				       crypto_aead_get_flags(tfm));
 
 				if (!template[i].fail)
-					goto next_one;
+					continue;
 			}
 
 			authsize = abs(template[i].rlen - template[i].ilen);
@@ -384,7 +361,7 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
 				printk(KERN_INFO
 				       "failed to set authsize = %u\n",
 				       authsize);
-				goto next_one;
+				continue;
 			}
 
 			sg_init_one(&sg[0], input,
@@ -416,7 +393,7 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
 			default:
 				printk(KERN_INFO "%s () failed err=%d\n",
 				       e, -ret);
-				goto next_one;
+				continue;
 			}
 
 			q = input;
@@ -425,11 +402,6 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
 			printk(KERN_INFO "enc/dec: %s\n",
 			       memcmp(q, template[i].result,
 				      template[i].rlen) ? "fail" : "pass");
-next_one:
-			if (!template[i].key)
-				kfree(key);
-			kfree(assoc);
-			kfree(input);
 		}
 	}
 
@@ -460,18 +432,32 @@ next_one:
 					goto out;
 			}
 
-			memset(xbuf, 0, XBUFSIZE);
+			authsize = abs(template[i].rlen - template[i].ilen);
+
 			sg_init_table(sg, template[i].np);
 			for (k = 0, temp = 0; k < template[i].np; k++) {
-				memcpy(&xbuf[IDX[k]],
-				       template[i].input + temp,
+				if (unlikely(offset_in_page(IDX[k]) +
+					     template[i].tap[k] > PAGE_SIZE)) {
+					WARN_ON(1);
+					goto out;
+				}
+
+				q = xbuf[IDX[k] >> PAGE_SHIFT] +
+				    offset_in_page(IDX[k]);
+
+				memcpy(q, template[i].input + temp,
 				       template[i].tap[k]);
+
+				n = template[i].tap[k];
+				if (k == template[i].np - 1 && enc)
+					n += authsize;
+				if (offset_in_page(q) + n < PAGE_SIZE)
+					q[n] = 0;
+
+				sg_set_buf(&sg[k], q, template[i].tap[k]);
 				temp += template[i].tap[k];
-				sg_set_buf(&sg[k], &xbuf[IDX[k]],
-					   template[i].tap[k]);
 			}
 
-			authsize = abs(template[i].rlen - template[i].ilen);
 			ret = crypto_aead_setauthsize(tfm, authsize);
 			if (ret) {
 				printk(KERN_INFO
@@ -480,17 +466,26 @@ next_one:
 				goto out;
 			}
 
-			if (enc)
+			if (enc) {
+				if (unlikely(sg[k - 1].offset +
+					     sg[k - 1].length + authsize >
+					     PAGE_SIZE)) {
+					WARN_ON(1);
+					goto out;
+				}
+
 				sg[k - 1].length += authsize;
+			}
 
 			sg_init_table(asg, template[i].anp);
 			for (k = 0, temp = 0; k < template[i].anp; k++) {
-				memcpy(&axbuf[IDX[k]],
-				       template[i].assoc + temp,
-				       template[i].atap[k]);
-				temp += template[i].atap[k];
-				sg_set_buf(&asg[k], &axbuf[IDX[k]],
+				sg_set_buf(&asg[k],
+					   memcpy(axbuf[IDX[k] >> PAGE_SHIFT] +
+						  offset_in_page(IDX[k]),
+						  template[i].assoc + temp,
+						  template[i].atap[k]),
 					   template[i].atap[k]);
+				temp += template[i].atap[k];
 			}
 
 			aead_request_set_crypt(req, sg, sg,
@@ -523,7 +518,8 @@ next_one:
 
 			for (k = 0, temp = 0; k < template[i].np; k++) {
 				printk(KERN_INFO "page %u\n", k);
-				q = &xbuf[IDX[k]];
+				q = xbuf[IDX[k] >> PAGE_SHIFT] +
+				    offset_in_page(IDX[k]);
 
 				n = template[i].tap[k];
 				if (k == template[i].np - 1)
@@ -541,7 +537,8 @@ next_one:
 					else
 						n = 0;
 				} else {
-					for (n = 0; q[n]; n++)
+					for (n = 0; offset_in_page(q + n) &&
+						    q[n]; n++)
 						;
 				}
 				if (n) {
@@ -600,12 +597,6 @@ static void test_cipher(char *algo, int enc,
 
 	j = 0;
 	for (i = 0; i < tcount; i++) {
-
-		data = kzalloc(template[i].ilen, GFP_KERNEL);
-		if (!data)
-			continue;
-
-		memcpy(data, template[i].input, template[i].ilen);
 		if (template[i].iv)
 			memcpy(iv, template[i].iv, MAX_IVLEN);
 		else
@@ -616,6 +607,9 @@ static void test_cipher(char *algo, int enc,
 			printk("test %u (%d bit key):\n",
 			j, template[i].klen * 8);
 
+			data = xbuf[0];
+			memcpy(data, template[i].input, template[i].ilen);
+
 			crypto_ablkcipher_clear_flags(tfm, ~0);
 			if (template[i].wk)
 				crypto_ablkcipher_set_flags(
@@ -627,10 +621,8 @@ static void test_cipher(char *algo, int enc,
 				printk("setkey() failed flags=%x\n",
 				       crypto_ablkcipher_get_flags(tfm));
 
-				if (!template[i].fail) {
-					kfree(data);
+				if (!template[i].fail)
 					goto out;
-				}
 			}
 
 			sg_init_one(&sg[0], data, template[i].ilen);
@@ -655,7 +647,6 @@ static void test_cipher(char *algo, int enc,
 				/* fall through */
 			default:
 				printk("%s () failed err=%d\n", e, -ret);
-				kfree(data);
 				goto out;
 			}
 
@@ -666,7 +657,6 @@ static void test_cipher(char *algo, int enc,
 			       memcmp(q, template[i].result,
 				      template[i].rlen) ? "fail" : "pass");
 		}
-		kfree(data);
 	}
 
 	printk("\ntesting %s %s across pages (chunking)\n", algo, e);
@@ -674,12 +664,6 @@ static void test_cipher(char *algo, int enc,
 	j = 0;
 	for (i = 0; i < tcount; i++) {
 
-		data = kzalloc(template[i].ilen, GFP_KERNEL);
-		if (!data)
-			continue;
-
-		memcpy(data, template[i].input, template[i].ilen);
-
 		if (template[i].iv)
 			memcpy(iv, template[i].iv, MAX_IVLEN);
 		else
@@ -690,7 +674,6 @@ static void test_cipher(char *algo, int enc,
 			printk("test %u (%d bit key):\n",
 			j, template[i].klen * 8);
 
-			memset(xbuf, 0, XBUFSIZE);
 			crypto_ablkcipher_clear_flags(tfm, ~0);
 			if (template[i].wk)
 				crypto_ablkcipher_set_flags(
@@ -702,21 +685,32 @@ static void test_cipher(char *algo, int enc,
 				printk("setkey() failed flags=%x\n",
 						crypto_ablkcipher_get_flags(tfm));
 
-				if (!template[i].fail) {
-					kfree(data);
+				if (!template[i].fail)
 					goto out;
-				}
 			}
 
 			temp = 0;
 			sg_init_table(sg, template[i].np);
 			for (k = 0; k < template[i].np; k++) {
-				memcpy(&xbuf[IDX[k]],
-						template[i].input + temp,
-						template[i].tap[k]);
+				if (unlikely(offset_in_page(IDX[k]) +
+					     template[i].tap[k] > PAGE_SIZE)) {
+					WARN_ON(1);
+					goto out;
+				}
+
+				q = xbuf[IDX[k] >> PAGE_SHIFT] +
+				    offset_in_page(IDX[k]);
+
+				memcpy(q, template[i].input + temp,
+				       template[i].tap[k]);
+
+				if (offset_in_page(q) + template[i].tap[k] <
+				    PAGE_SIZE)
+					q[template[i].tap[k]] = 0;
+
+				sg_set_buf(&sg[k], q, template[i].tap[k]);
+
 				temp += template[i].tap[k];
-				sg_set_buf(&sg[k], &xbuf[IDX[k]],
-						template[i].tap[k]);
 			}
 
 			ablkcipher_request_set_crypt(req, sg, sg,
@@ -746,19 +740,21 @@ static void test_cipher(char *algo, int enc,
 			temp = 0;
 			for (k = 0; k < template[i].np; k++) {
 				printk("page %u\n", k);
-				q = &xbuf[IDX[k]];
+				q = xbuf[IDX[k] >> PAGE_SHIFT] +
+				    offset_in_page(IDX[k]);
 				hexdump(q, template[i].tap[k]);
 				printk("%s\n",
 					memcmp(q, template[i].result + temp,
 						template[i].tap[k]) ? "fail" :
 					"pass");
 
-				for (n = 0; q[template[i].tap[k] + n]; n++)
+				q += template[i].tap[k];
+				for (n = 0; offset_in_page(q + n) && q[n]; n++)
 					;
 				if (n) {
 					printk("Result buffer corruption %u "
 					       "bytes:\n", n);
-					hexdump(&q[template[i].tap[k]], n);
+					hexdump(q, n);
 				}
 				temp += template[i].tap[k];
 			}
@@ -769,16 +765,13 @@ out:
 	ablkcipher_request_free(req);
 }
 
-static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc, char *p,
-			       int blen, int sec)
+static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc,
+			       struct scatterlist *sg, int blen, int sec)
 {
-	struct scatterlist sg[1];
 	unsigned long start, end;
 	int bcount;
 	int ret;
 
-	sg_init_one(sg, p, blen);
-
 	for (start = jiffies, end = start + sec * HZ, bcount = 0;
 	     time_before(jiffies, end); bcount++) {
 		if (enc)
@@ -795,16 +788,13 @@ static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc, char *p,
 	return 0;
 }
 
-static int test_cipher_cycles(struct blkcipher_desc *desc, int enc, char *p,
-			      int blen)
+static int test_cipher_cycles(struct blkcipher_desc *desc, int enc,
+			      struct scatterlist *sg, int blen)
 {
-	struct scatterlist sg[1];
 	unsigned long cycles = 0;
 	int ret = 0;
 	int i;
 
-	sg_init_one(sg, p, blen);
-
 	local_bh_disable();
 	local_irq_disable();
 
@@ -854,7 +844,7 @@ static void test_cipher_speed(char *algo, int enc, unsigned int sec,
 			      unsigned int tcount, u8 *keysize)
 {
 	unsigned int ret, i, j, iv_len;
-	unsigned char *key, *p, iv[128];
+	unsigned char *key, iv[128];
 	struct crypto_blkcipher *tfm;
 	struct blkcipher_desc desc;
 	const char *e;
@@ -882,27 +872,28 @@ static void test_cipher_speed(char *algo, int enc, unsigned int sec,
 
 		b_size = block_sizes;
 		do {
+			struct scatterlist sg[TVMEMSIZE];
 
-			if ((*keysize + *b_size) > TVMEMSIZE) {
-				printk("template (%u) too big for tvmem (%u)\n",
-						*keysize + *b_size, TVMEMSIZE);
+			if ((*keysize + *b_size) > TVMEMSIZE * PAGE_SIZE) {
+				printk("template (%u) too big for "
+				       "tvmem (%lu)\n", *keysize + *b_size,
+				       TVMEMSIZE * PAGE_SIZE);
 				goto out;
 			}
 
 			printk("test %u (%d bit key, %d byte blocks): ", i,
 					*keysize * 8, *b_size);
 
-			memset(tvmem, 0xff, *keysize + *b_size);
+			memset(tvmem[0], 0xff, PAGE_SIZE);
 
 			/* set key, plain text and IV */
-			key = (unsigned char *)tvmem;
+			key = (unsigned char *)tvmem[0];
 			for (j = 0; j < tcount; j++) {
 				if (template[j].klen == *keysize) {
 					key = template[j].key;
 					break;
 				}
 			}
-			p = (unsigned char *)tvmem + *keysize;
 
 			ret = crypto_blkcipher_setkey(tfm, key, *keysize);
 			if (ret) {
@@ -911,6 +902,14 @@ static void test_cipher_speed(char *algo, int enc, unsigned int sec,
 				goto out;
 			}
 
+			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_blkcipher_ivsize(tfm);
 			if (iv_len) {
 				memset(&iv, 0xff, iv_len);
@@ -918,9 +917,11 @@ static void test_cipher_speed(char *algo, int enc, unsigned int sec,
 			}
 
 			if (sec)
-				ret = test_cipher_jiffies(&desc, enc, p, *b_size, sec);
+				ret = test_cipher_jiffies(&desc, enc, sg,
+							  *b_size, sec);
 			else
-				ret = test_cipher_cycles(&desc, enc, p, *b_size);
+				ret = test_cipher_cycles(&desc, enc, sg,
+							 *b_size);
 
 			if (ret) {
 				printk("%s() failed flags=%x\n", e, desc.flags);
@@ -936,10 +937,9 @@ out:
 	crypto_free_blkcipher(tfm);
 }
 
-static void test_digest_jiffies(struct crypto_tfm *tfm, char *p, int blen,
-				int plen, char *out, int sec)
+static void test_digest_jiffies(struct crypto_tfm *tfm, struct scatterlist *sg,
+				int blen, int plen, char *out, int sec)
 {
-	struct scatterlist sg[1];
 	unsigned long start, end;
 	int bcount, pcount;
 
@@ -947,7 +947,6 @@ static void test_digest_jiffies(struct crypto_tfm *tfm, char *p, int blen,
 	     time_before(jiffies, end); bcount++) {
 		crypto_digest_init(tfm);
 		for (pcount = 0; pcount < blen; pcount += plen) {
-			sg_set_buf(sg, p + pcount, plen);
 			crypto_digest_update(tfm, sg, 1);
 		}
 		/* we assume there is enough space in 'out' for the result */
@@ -960,10 +959,9 @@ static void test_digest_jiffies(struct crypto_tfm *tfm, char *p, int blen,
 	return;
 }
 
-static void test_digest_cycles(struct crypto_tfm *tfm, char *p, int blen,
-			       int plen, char *out)
+static void test_digest_cycles(struct crypto_tfm *tfm, struct scatterlist *sg,
+			       int blen, int plen, char *out)
 {
-	struct scatterlist sg[1];
 	unsigned long cycles = 0;
 	int i, pcount;
 
@@ -974,7 +972,6 @@ static void test_digest_cycles(struct crypto_tfm *tfm, char *p, int blen,
 	for (i = 0; i < 4; i++) {
 		crypto_digest_init(tfm);
 		for (pcount = 0; pcount < blen; pcount += plen) {
-			sg_set_buf(sg, p + pcount, plen);
 			crypto_digest_update(tfm, sg, 1);
 		}
 		crypto_digest_final(tfm, out);
@@ -989,7 +986,6 @@ static void test_digest_cycles(struct crypto_tfm *tfm, char *p, int blen,
 		start = get_cycles();
 
 		for (pcount = 0; pcount < blen; pcount += plen) {
-			sg_set_buf(sg, p + pcount, plen);
 			crypto_digest_update(tfm, sg, 1);
 		}
 		crypto_digest_final(tfm, out);
@@ -1011,6 +1007,7 @@ static void test_digest_cycles(struct crypto_tfm *tfm, char *p, int blen,
 static void test_digest_speed(char *algo, unsigned int sec,
 			      struct digest_speed *speed)
 {
+	struct scatterlist sg[TVMEMSIZE];
 	struct crypto_tfm *tfm;
 	char output[1024];
 	int i;
@@ -1030,22 +1027,26 @@ static void test_digest_speed(char *algo, unsigned int sec,
 		goto out;
 	}
 
+	sg_init_table(sg, TVMEMSIZE);
+	for (i = 0; i < TVMEMSIZE; i++) {
+		sg_set_buf(sg + i, tvmem[i], PAGE_SIZE);
+		memset(tvmem[i], 0xff, PAGE_SIZE);
+	}
+
 	for (i = 0; speed[i].blen != 0; i++) {
-		if (speed[i].blen > TVMEMSIZE) {
-			printk("template (%u) too big for tvmem (%u)\n",
-			       speed[i].blen, TVMEMSIZE);
+		if (speed[i].blen > TVMEMSIZE * PAGE_SIZE) {
+			printk("template (%u) too big for tvmem (%lu)\n",
+			       speed[i].blen, TVMEMSIZE * PAGE_SIZE);
 			goto out;
 		}
 
 		printk("test%3u (%5u byte blocks,%5u bytes per update,%4u updates): ",
 		       i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen);
 
-		memset(tvmem, 0xff, speed[i].blen);
-
 		if (sec)
-			test_digest_jiffies(tfm, tvmem, speed[i].blen, speed[i].plen, output, sec);
+			test_digest_jiffies(tfm, sg, speed[i].blen, speed[i].plen, output, sec);
 		else
-			test_digest_cycles(tfm, tvmem, speed[i].blen, speed[i].plen, output);
+			test_digest_cycles(tfm, sg, speed[i].blen, speed[i].plen, output);
 	}
 
 out:
@@ -1057,7 +1058,6 @@ static void test_deflate(void)
 	unsigned int i;
 	char result[COMP_BUF_SIZE];
 	struct crypto_tfm *tfm;
-	unsigned int tsize;
 
 	printk("\ntesting deflate compression\n");
 
@@ -1090,13 +1090,6 @@ static void test_deflate(void)
 
 	printk("\ntesting deflate decompression\n");
 
-	tsize = sizeof (deflate_decomp_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		goto out;
-	}
-
 	for (i = 0; i < DEFLATE_DECOMP_TEST_VECTORS; i++) {
 		int ilen, ret, dlen = COMP_BUF_SIZE;
 
@@ -1117,7 +1110,7 @@ static void test_deflate(void)
 			      dlen) ? "fail" : "pass",
 		       ilen, dlen);
 	}
-out:
+
 	crypto_free_tfm(tfm);
 }
 
@@ -1747,18 +1740,25 @@ static void do_test(void)
 static int __init init(void)
 {
 	int err = -ENOMEM;
+	int i;
 
-	tvmem = kmalloc(TVMEMSIZE, GFP_KERNEL);
-	if (tvmem == NULL)
-		return err;
+	for (i = 0; i < TVMEMSIZE; i++) {
+		tvmem[i] = (void *)__get_free_page(GFP_KERNEL);
+		if (!tvmem[i])
+			goto err_free_tv;
+	}
 
-	xbuf = kmalloc(XBUFSIZE, GFP_KERNEL);
-	if (xbuf == NULL)
-		goto err_free_tv;
+	for (i = 0; i < XBUFSIZE; i++) {
+		xbuf[i] = (void *)__get_free_page(GFP_KERNEL);
+		if (!xbuf[i])
+			goto err_free_xbuf;
+	}
 
-	axbuf = kmalloc(XBUFSIZE, GFP_KERNEL);
-	if (axbuf == NULL)
-		goto err_free_xbuf;
+	for (i = 0; i < XBUFSIZE; i++) {
+		axbuf[i] = (void *)__get_free_page(GFP_KERNEL);
+		if (!axbuf[i])
+			goto err_free_axbuf;
+	}
 
 	do_test();
 
@@ -1770,11 +1770,15 @@ static int __init init(void)
 	 */
 	err = -EAGAIN;
 
-	kfree(axbuf);
- err_free_xbuf:
-	kfree(xbuf);
- err_free_tv:
-	kfree(tvmem);
+err_free_axbuf:
+	for (i = 0; i < XBUFSIZE && axbuf[i]; i++)
+		free_page((unsigned long)axbuf[i]);
+err_free_xbuf:
+	for (i = 0; i < XBUFSIZE && xbuf[i]; i++)
+		free_page((unsigned long)xbuf[i]);
+err_free_tv:
+	for (i = 0; i < TVMEMSIZE && tvmem[i]; i++)
+		free_page((unsigned long)tvmem[i]);
 
 	return err;
 }
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
index fd8aa75..09d5f8a 100644
--- a/crypto/tcrypt.h
+++ b/crypto/tcrypt.h
@@ -43,7 +43,7 @@ struct cipher_testvec {
 	char *iv;
 	char *input;
 	char *result;
-	unsigned char tap[MAX_TAP];
+	unsigned short tap[MAX_TAP];
 	int np;
 	unsigned char fail;
 	unsigned char wk; /* weak key flag */
@@ -3433,6 +3433,8 @@ static struct cipher_testvec aes_ctr_enc_tv_template[] = {
 			"\x4b\xef\x31\x18\xea\xac\xb1\x84"
 			"\x21\xed\xda\x86",
 		.rlen = 4100,
+		.np	= 2,
+		.tap	= { 4064, 36 },
 	},
 };