Beispiel #1
0
static int crypto_ctr_crypt(struct blkcipher_desc *desc,
			      struct scatterlist *dst, struct scatterlist *src,
			      unsigned int nbytes)
{
	struct blkcipher_walk walk;
	struct crypto_blkcipher *tfm = desc->tfm;
	struct crypto_ctr_ctx *ctx = crypto_blkcipher_ctx(tfm);
	struct crypto_cipher *child = ctx->child;
	unsigned int bsize = crypto_cipher_blocksize(child);
	int err;

	blkcipher_walk_init(&walk, dst, src, nbytes);
	err = blkcipher_walk_virt_block(desc, &walk, bsize);

	while (walk.nbytes >= bsize) {
		if (walk.src.virt.addr == walk.dst.virt.addr)
			nbytes = crypto_ctr_crypt_inplace(&walk, child);
		else
			nbytes = crypto_ctr_crypt_segment(&walk, child);

		err = blkcipher_walk_done(desc, &walk, nbytes);
	}

	if (walk.nbytes) {
		crypto_ctr_crypt_final(&walk, child);
		err = blkcipher_walk_done(desc, &walk, 0);
	}

	return err;
}
Beispiel #2
0
static int crypto_ctr_crypt(struct skcipher_request *req)
{
	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
	struct crypto_cipher *cipher = skcipher_cipher_simple(tfm);
	const unsigned int bsize = crypto_cipher_blocksize(cipher);
	struct skcipher_walk walk;
	unsigned int nbytes;
	int err;

	err = skcipher_walk_virt(&walk, req, false);

	while (walk.nbytes >= bsize) {
		if (walk.src.virt.addr == walk.dst.virt.addr)
			nbytes = crypto_ctr_crypt_inplace(&walk, cipher);
		else
			nbytes = crypto_ctr_crypt_segment(&walk, cipher);

		err = skcipher_walk_done(&walk, nbytes);
	}

	if (walk.nbytes) {
		crypto_ctr_crypt_final(&walk, cipher);
		err = skcipher_walk_done(&walk, 0);
	}

	return err;
}
Beispiel #3
0
static int crypto_ctr_crypt(struct blkcipher_desc *desc,
			      struct scatterlist *dst, struct scatterlist *src,
			      unsigned int nbytes)
{
	struct blkcipher_walk walk;
	struct crypto_blkcipher *tfm = desc->tfm;
	struct crypto_ctr_ctx *ctx = crypto_blkcipher_ctx(tfm);
	struct crypto_cipher *child = ctx->child;
	unsigned int bsize = crypto_cipher_blocksize(child);
	int err;

	blkcipher_walk_init(&walk, dst, src, nbytes);
	err = blkcipher_walk_virt_block(desc, &walk, bsize);

	while (walk.nbytes >= bsize) {

#ifdef CONFIG_CRYPTO_DEV_REALTEK
		if (ctx->rtl_ctx.mode >= 0)
		{
			int i, over_flag = 0;
			unsigned int one = 0, len = 0;			
			u8 over_iv[32] = {0};
			u8 *src = walk.src.virt.addr;
			u8 *dst = walk.dst.virt.addr;
			/* hw CTRBLK overflow handle different with linux kernel
			 *  hw engine: CTRBLK := NONCE || IV || ONE,  NONCE 4 bytes, IV 8bytes, ONE 4bytes 
			 *  hw engine only the ONE(4bytes) is treated as counter bytes
			 *  linux kernel uses the second method, which means the entire byte block is treated as counter bytes
			 */
			over_flag = 0;
			one = *((unsigned int *)(walk.iv + bsize - 4));
			for (i = 0; i < (walk.nbytes / bsize); i++)
			{					
				if (one == 0xffffffff)
				{
					//printk("%s %d i=%d one=%u\n", __FUNCTION__, __LINE__, i, one);
					over_flag = 1;
					break;
				}
				one++;
			}
			if (over_flag)
			{
				//before ONE overflow 
				len = bsize*(i+1);
				nbytes = rtl_cipher_crypt(child, 1,
				&ctx->rtl_ctx, walk.src.virt.addr, len,
				walk.iv, walk.dst.virt.addr);
				//printk("%s %d len=%u nbytes=%u \n", __FUNCTION__, __LINE__, len, nbytes);
				src += (len - nbytes);
				dst += (len - nbytes);
								
				//after ONE overflow,update IV
				memcpy(over_iv, walk.iv, bsize - 4);
				crypto_inc(over_iv, bsize-4);
				memcpy(walk.iv, over_iv, bsize);
				
				nbytes = rtl_cipher_crypt(child, 1,
				&ctx->rtl_ctx, src, walk.nbytes -len,
				walk.iv, dst);
				
				/* increment counter in counterblock */
				for (i = 0; i < ((walk.nbytes -len) / bsize); i++)
					crypto_inc(walk.iv, bsize);
				
				if (walk.src.virt.addr == walk.dst.virt.addr)
				{
					src += ((walk.nbytes -len) - nbytes);
				}
				else
				{
					src += ((walk.nbytes -len) - nbytes);
					dst += ((walk.nbytes -len) - nbytes);
				}
				
			}
			else
			{
				nbytes = rtl_cipher_crypt(child, 1,
					&ctx->rtl_ctx, walk.src.virt.addr, walk.nbytes,
					walk.iv, walk.dst.virt.addr);		
				if (walk.src.virt.addr == walk.dst.virt.addr)
				{
					walk.src.virt.addr += (walk.nbytes - nbytes);
				}
				else
				{
					walk.dst.virt.addr += (walk.nbytes - nbytes);
					walk.dst.virt.addr += (walk.nbytes - nbytes);
				}
				/* increment counter in counterblock */
				for (i = 0; i < (walk.nbytes / bsize); i++)
					crypto_inc(walk.iv, bsize);
			}

			err = blkcipher_walk_done(desc, &walk, nbytes);
			continue;
		}
#endif

		if (walk.src.virt.addr == walk.dst.virt.addr)
			nbytes = crypto_ctr_crypt_inplace(&walk, child);
		else
			nbytes = crypto_ctr_crypt_segment(&walk, child);

		err = blkcipher_walk_done(desc, &walk, nbytes);
	}

	if (walk.nbytes) {
		crypto_ctr_crypt_final(&walk, child);
		err = blkcipher_walk_done(desc, &walk, 0);
	}

	return err;
}