crypto: cavium/nitrox - Fix cbc ciphers self test failures
Self test failures are due to wrong output IV. This patch fixes this issue by copying back output IV into skcipher request. Signed-off-by: Nagadheeraj Rottela <rnagadheeraj@marvell.com> Reviewed-by: Srikanth Jampala <jsrikanth@marvell.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
		
							parent
							
								
									3fed9baad5
								
							
						
					
					
						commit
						ced0a170fd
					
				| @ -10,6 +10,8 @@ | ||||
| #define PENDING_SIG	0xFFFFFFFFFFFFFFFFUL | ||||
| #define PRIO 4001 | ||||
| 
 | ||||
| typedef void (*sereq_completion_t)(void *req, int err); | ||||
| 
 | ||||
| /**
 | ||||
|  * struct gphdr - General purpose Header | ||||
|  * @param0: first parameter. | ||||
| @ -203,12 +205,14 @@ struct nitrox_crypto_ctx { | ||||
| 		struct flexi_crypto_context *fctx; | ||||
| 	} u; | ||||
| 	struct crypto_ctx_hdr *chdr; | ||||
| 	sereq_completion_t callback; | ||||
| }; | ||||
| 
 | ||||
| struct nitrox_kcrypt_request { | ||||
| 	struct se_crypto_request creq; | ||||
| 	u8 *src; | ||||
| 	u8 *dst; | ||||
| 	u8 *iv_out; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  | ||||
| @ -6,6 +6,7 @@ | ||||
| 
 | ||||
| #include <crypto/aes.h> | ||||
| #include <crypto/skcipher.h> | ||||
| #include <crypto/scatterwalk.h> | ||||
| #include <crypto/ctr.h> | ||||
| #include <crypto/internal/des.h> | ||||
| #include <crypto/xts.h> | ||||
| @ -47,6 +48,63 @@ static enum flexi_cipher flexi_cipher_type(const char *name) | ||||
| 	return cipher->value; | ||||
| } | ||||
| 
 | ||||
| static void free_src_sglist(struct skcipher_request *skreq) | ||||
| { | ||||
| 	struct nitrox_kcrypt_request *nkreq = skcipher_request_ctx(skreq); | ||||
| 
 | ||||
| 	kfree(nkreq->src); | ||||
| } | ||||
| 
 | ||||
| static void free_dst_sglist(struct skcipher_request *skreq) | ||||
| { | ||||
| 	struct nitrox_kcrypt_request *nkreq = skcipher_request_ctx(skreq); | ||||
| 
 | ||||
| 	kfree(nkreq->dst); | ||||
| } | ||||
| 
 | ||||
| static void nitrox_skcipher_callback(void *arg, int err) | ||||
| { | ||||
| 	struct skcipher_request *skreq = arg; | ||||
| 
 | ||||
| 	free_src_sglist(skreq); | ||||
| 	free_dst_sglist(skreq); | ||||
| 	if (err) { | ||||
| 		pr_err_ratelimited("request failed status 0x%0x\n", err); | ||||
| 		err = -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	skcipher_request_complete(skreq, err); | ||||
| } | ||||
| 
 | ||||
| static void nitrox_cbc_cipher_callback(void *arg, int err) | ||||
| { | ||||
| 	struct skcipher_request *skreq = arg; | ||||
| 	struct nitrox_kcrypt_request *nkreq = skcipher_request_ctx(skreq); | ||||
| 	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(skreq); | ||||
| 	int ivsize = crypto_skcipher_ivsize(cipher); | ||||
| 	unsigned int start = skreq->cryptlen - ivsize; | ||||
| 
 | ||||
| 	if (err) { | ||||
| 		nitrox_skcipher_callback(arg, err); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	if (nkreq->creq.ctrl.s.arg == ENCRYPT) { | ||||
| 		scatterwalk_map_and_copy(skreq->iv, skreq->dst, start, ivsize, | ||||
| 					 0); | ||||
| 	} else { | ||||
| 		if (skreq->src != skreq->dst) { | ||||
| 			scatterwalk_map_and_copy(skreq->iv, skreq->src, start, | ||||
| 						 ivsize, 0); | ||||
| 		} else { | ||||
| 			memcpy(skreq->iv, nkreq->iv_out, ivsize); | ||||
| 			kfree(nkreq->iv_out); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	nitrox_skcipher_callback(arg, err); | ||||
| } | ||||
| 
 | ||||
| static int nitrox_skcipher_init(struct crypto_skcipher *tfm) | ||||
| { | ||||
| 	struct nitrox_crypto_ctx *nctx = crypto_skcipher_ctx(tfm); | ||||
| @ -63,6 +121,8 @@ static int nitrox_skcipher_init(struct crypto_skcipher *tfm) | ||||
| 		nitrox_put_device(nctx->ndev); | ||||
| 		return -ENOMEM; | ||||
| 	} | ||||
| 
 | ||||
| 	nctx->callback = nitrox_skcipher_callback; | ||||
| 	nctx->chdr = chdr; | ||||
| 	nctx->u.ctx_handle = (uintptr_t)((u8 *)chdr->vaddr + | ||||
| 					 sizeof(struct ctx_hdr)); | ||||
| @ -71,6 +131,19 @@ static int nitrox_skcipher_init(struct crypto_skcipher *tfm) | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int nitrox_cbc_init(struct crypto_skcipher *tfm) | ||||
| { | ||||
| 	int err; | ||||
| 	struct nitrox_crypto_ctx *nctx = crypto_skcipher_ctx(tfm); | ||||
| 
 | ||||
| 	err = nitrox_skcipher_init(tfm); | ||||
| 	if (err) | ||||
| 		return err; | ||||
| 
 | ||||
| 	nctx->callback = nitrox_cbc_cipher_callback; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void nitrox_skcipher_exit(struct crypto_skcipher *tfm) | ||||
| { | ||||
| 	struct nitrox_crypto_ctx *nctx = crypto_skcipher_ctx(tfm); | ||||
| @ -173,34 +246,6 @@ static int alloc_dst_sglist(struct skcipher_request *skreq, int ivsize) | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void free_src_sglist(struct skcipher_request *skreq) | ||||
| { | ||||
| 	struct nitrox_kcrypt_request *nkreq = skcipher_request_ctx(skreq); | ||||
| 
 | ||||
| 	kfree(nkreq->src); | ||||
| } | ||||
| 
 | ||||
| static void free_dst_sglist(struct skcipher_request *skreq) | ||||
| { | ||||
| 	struct nitrox_kcrypt_request *nkreq = skcipher_request_ctx(skreq); | ||||
| 
 | ||||
| 	kfree(nkreq->dst); | ||||
| } | ||||
| 
 | ||||
| static void nitrox_skcipher_callback(void *arg, int err) | ||||
| { | ||||
| 	struct skcipher_request *skreq = arg; | ||||
| 
 | ||||
| 	free_src_sglist(skreq); | ||||
| 	free_dst_sglist(skreq); | ||||
| 	if (err) { | ||||
| 		pr_err_ratelimited("request failed status 0x%0x\n", err); | ||||
| 		err = -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	skcipher_request_complete(skreq, err); | ||||
| } | ||||
| 
 | ||||
| static int nitrox_skcipher_crypt(struct skcipher_request *skreq, bool enc) | ||||
| { | ||||
| 	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(skreq); | ||||
| @ -240,8 +285,28 @@ static int nitrox_skcipher_crypt(struct skcipher_request *skreq, bool enc) | ||||
| 	} | ||||
| 
 | ||||
| 	/* send the crypto request */ | ||||
| 	return nitrox_process_se_request(nctx->ndev, creq, | ||||
| 					 nitrox_skcipher_callback, skreq); | ||||
| 	return nitrox_process_se_request(nctx->ndev, creq, nctx->callback, | ||||
| 					 skreq); | ||||
| } | ||||
| 
 | ||||
| static int nitrox_cbc_decrypt(struct skcipher_request *skreq) | ||||
| { | ||||
| 	struct nitrox_kcrypt_request *nkreq = skcipher_request_ctx(skreq); | ||||
| 	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(skreq); | ||||
| 	int ivsize = crypto_skcipher_ivsize(cipher); | ||||
| 	gfp_t flags = (skreq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? | ||||
| 			GFP_KERNEL : GFP_ATOMIC; | ||||
| 	unsigned int start = skreq->cryptlen - ivsize; | ||||
| 
 | ||||
| 	if (skreq->src != skreq->dst) | ||||
| 		return nitrox_skcipher_crypt(skreq, false); | ||||
| 
 | ||||
| 	nkreq->iv_out = kmalloc(ivsize, flags); | ||||
| 	if (!nkreq->iv_out) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	scatterwalk_map_and_copy(nkreq->iv_out, skreq->src, start, ivsize, 0); | ||||
| 	return nitrox_skcipher_crypt(skreq, false); | ||||
| } | ||||
| 
 | ||||
| static int nitrox_aes_encrypt(struct skcipher_request *skreq) | ||||
| @ -340,8 +405,8 @@ static struct skcipher_alg nitrox_skciphers[] = { { | ||||
| 	.ivsize = AES_BLOCK_SIZE, | ||||
| 	.setkey = nitrox_aes_setkey, | ||||
| 	.encrypt = nitrox_aes_encrypt, | ||||
| 	.decrypt = nitrox_aes_decrypt, | ||||
| 	.init = nitrox_skcipher_init, | ||||
| 	.decrypt = nitrox_cbc_decrypt, | ||||
| 	.init = nitrox_cbc_init, | ||||
| 	.exit = nitrox_skcipher_exit, | ||||
| }, { | ||||
| 	.base = { | ||||
| @ -455,8 +520,8 @@ static struct skcipher_alg nitrox_skciphers[] = { { | ||||
| 	.ivsize = DES3_EDE_BLOCK_SIZE, | ||||
| 	.setkey = nitrox_3des_setkey, | ||||
| 	.encrypt = nitrox_3des_encrypt, | ||||
| 	.decrypt = nitrox_3des_decrypt, | ||||
| 	.init = nitrox_skcipher_init, | ||||
| 	.decrypt = nitrox_cbc_decrypt, | ||||
| 	.init = nitrox_cbc_init, | ||||
| 	.exit = nitrox_skcipher_exit, | ||||
| }, { | ||||
| 	.base = { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user