crypto: sun4i-ss - fallback when length is not multiple of blocksize
sun4i-ss does not handle requests when length are not a multiple of
blocksize.
This patch adds a fallback for that case.
Fixes: 6298e94821 ("crypto: sunxi-ss - Add Allwinner Security System crypto accelerator")
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
			
			
This commit is contained in:
		
							parent
							
								
									f87391558a
								
							
						
					
					
						commit
						0ae1f46c55
					
				| @ -129,6 +129,8 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) | ||||
| 	struct scatterlist *out_sg = areq->dst; | ||||
| 	unsigned int ivsize = crypto_skcipher_ivsize(tfm); | ||||
| 	struct sun4i_cipher_req_ctx *ctx = skcipher_request_ctx(areq); | ||||
| 	struct skcipher_alg *alg = crypto_skcipher_alg(tfm); | ||||
| 	struct sun4i_ss_alg_template *algt; | ||||
| 	u32 mode = ctx->mode; | ||||
| 	/* when activating SS, the default FIFO space is SS_RX_DEFAULT(32) */ | ||||
| 	u32 rx_cnt = SS_RX_DEFAULT; | ||||
| @ -148,6 +150,7 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) | ||||
| 	unsigned int obo = 0;	/* offset in bufo*/ | ||||
| 	unsigned int obl = 0;	/* length of data in bufo */ | ||||
| 	unsigned long flags; | ||||
| 	bool need_fallback; | ||||
| 
 | ||||
| 	if (!areq->cryptlen) | ||||
| 		return 0; | ||||
| @ -157,6 +160,10 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	algt = container_of(alg, struct sun4i_ss_alg_template, alg.crypto); | ||||
| 	if (areq->cryptlen % algt->alg.crypto.base.cra_blocksize) | ||||
| 		need_fallback = true; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * if we have only SGs with size multiple of 4, | ||||
| 	 * we can use the SS optimized function | ||||
| @ -172,9 +179,24 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) | ||||
| 		out_sg = sg_next(out_sg); | ||||
| 	} | ||||
| 
 | ||||
| 	if (no_chunk == 1) | ||||
| 	if (no_chunk == 1 && !need_fallback) | ||||
| 		return sun4i_ss_opti_poll(areq); | ||||
| 
 | ||||
| 	if (need_fallback) { | ||||
| 		SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, op->fallback_tfm); | ||||
| 		skcipher_request_set_sync_tfm(subreq, op->fallback_tfm); | ||||
| 		skcipher_request_set_callback(subreq, areq->base.flags, NULL, | ||||
| 					      NULL); | ||||
| 		skcipher_request_set_crypt(subreq, areq->src, areq->dst, | ||||
| 					   areq->cryptlen, areq->iv); | ||||
| 		if (ctx->mode & SS_DECRYPTION) | ||||
| 			err = crypto_skcipher_decrypt(subreq); | ||||
| 		else | ||||
| 			err = crypto_skcipher_encrypt(subreq); | ||||
| 		skcipher_request_zero(subreq); | ||||
| 		return err; | ||||
| 	} | ||||
| 
 | ||||
| 	spin_lock_irqsave(&ss->slock, flags); | ||||
| 
 | ||||
| 	for (i = 0; i < op->keylen; i += 4) | ||||
| @ -448,6 +470,7 @@ int sun4i_ss_cipher_init(struct crypto_tfm *tfm) | ||||
| { | ||||
| 	struct sun4i_tfm_ctx *op = crypto_tfm_ctx(tfm); | ||||
| 	struct sun4i_ss_alg_template *algt; | ||||
| 	const char *name = crypto_tfm_alg_name(tfm); | ||||
| 
 | ||||
| 	memset(op, 0, sizeof(struct sun4i_tfm_ctx)); | ||||
| 
 | ||||
| @ -458,9 +481,22 @@ int sun4i_ss_cipher_init(struct crypto_tfm *tfm) | ||||
| 	crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm), | ||||
| 				    sizeof(struct sun4i_cipher_req_ctx)); | ||||
| 
 | ||||
| 	op->fallback_tfm = crypto_alloc_sync_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); | ||||
| 	if (IS_ERR(op->fallback_tfm)) { | ||||
| 		dev_err(op->ss->dev, "ERROR: Cannot allocate fallback for %s %ld\n", | ||||
| 			name, PTR_ERR(op->fallback_tfm)); | ||||
| 		return PTR_ERR(op->fallback_tfm); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void sun4i_ss_cipher_exit(struct crypto_tfm *tfm) | ||||
| { | ||||
| 	struct sun4i_tfm_ctx *op = crypto_tfm_ctx(tfm); | ||||
| 	crypto_free_sync_skcipher(op->fallback_tfm); | ||||
| } | ||||
| 
 | ||||
| /* check and set the AES key, prepare the mode to be used */ | ||||
| int sun4i_ss_aes_setkey(struct crypto_skcipher *tfm, const u8 *key, | ||||
| 			unsigned int keylen) | ||||
| @ -485,7 +521,11 @@ int sun4i_ss_aes_setkey(struct crypto_skcipher *tfm, const u8 *key, | ||||
| 	} | ||||
| 	op->keylen = keylen; | ||||
| 	memcpy(op->key, key, keylen); | ||||
| 	return 0; | ||||
| 
 | ||||
| 	crypto_sync_skcipher_clear_flags(op->fallback_tfm, CRYPTO_TFM_REQ_MASK); | ||||
| 	crypto_sync_skcipher_set_flags(op->fallback_tfm, tfm->base.crt_flags & CRYPTO_TFM_REQ_MASK); | ||||
| 
 | ||||
| 	return crypto_sync_skcipher_setkey(op->fallback_tfm, key, keylen); | ||||
| } | ||||
| 
 | ||||
| /* check and set the DES key, prepare the mode to be used */ | ||||
| @ -515,7 +555,11 @@ int sun4i_ss_des_setkey(struct crypto_skcipher *tfm, const u8 *key, | ||||
| 
 | ||||
| 	op->keylen = keylen; | ||||
| 	memcpy(op->key, key, keylen); | ||||
| 	return 0; | ||||
| 
 | ||||
| 	crypto_sync_skcipher_clear_flags(op->fallback_tfm, CRYPTO_TFM_REQ_MASK); | ||||
| 	crypto_sync_skcipher_set_flags(op->fallback_tfm, tfm->base.crt_flags & CRYPTO_TFM_REQ_MASK); | ||||
| 
 | ||||
| 	return crypto_sync_skcipher_setkey(op->fallback_tfm, key, keylen); | ||||
| } | ||||
| 
 | ||||
| /* check and set the 3DES key, prepare the mode to be used */ | ||||
| @ -531,5 +575,10 @@ int sun4i_ss_des3_setkey(struct crypto_skcipher *tfm, const u8 *key, | ||||
| 
 | ||||
| 	op->keylen = keylen; | ||||
| 	memcpy(op->key, key, keylen); | ||||
| 	return 0; | ||||
| 
 | ||||
| 	crypto_sync_skcipher_clear_flags(op->fallback_tfm, CRYPTO_TFM_REQ_MASK); | ||||
| 	crypto_sync_skcipher_set_flags(op->fallback_tfm, tfm->base.crt_flags & CRYPTO_TFM_REQ_MASK); | ||||
| 
 | ||||
| 	return crypto_sync_skcipher_setkey(op->fallback_tfm, key, keylen); | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -92,11 +92,12 @@ static struct sun4i_ss_alg_template ss_algs[] = { | ||||
| 			.cra_driver_name = "cbc-aes-sun4i-ss", | ||||
| 			.cra_priority = 300, | ||||
| 			.cra_blocksize = AES_BLOCK_SIZE, | ||||
| 			.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY, | ||||
| 			.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_NEED_FALLBACK, | ||||
| 			.cra_ctxsize = sizeof(struct sun4i_tfm_ctx), | ||||
| 			.cra_module = THIS_MODULE, | ||||
| 			.cra_alignmask = 3, | ||||
| 			.cra_init = sun4i_ss_cipher_init, | ||||
| 			.cra_exit = sun4i_ss_cipher_exit, | ||||
| 		} | ||||
| 	} | ||||
| }, | ||||
| @ -112,11 +113,12 @@ static struct sun4i_ss_alg_template ss_algs[] = { | ||||
| 			.cra_driver_name = "ecb-aes-sun4i-ss", | ||||
| 			.cra_priority = 300, | ||||
| 			.cra_blocksize = AES_BLOCK_SIZE, | ||||
| 			.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY, | ||||
| 			.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_NEED_FALLBACK, | ||||
| 			.cra_ctxsize = sizeof(struct sun4i_tfm_ctx), | ||||
| 			.cra_module = THIS_MODULE, | ||||
| 			.cra_alignmask = 3, | ||||
| 			.cra_init = sun4i_ss_cipher_init, | ||||
| 			.cra_exit = sun4i_ss_cipher_exit, | ||||
| 		} | ||||
| 	} | ||||
| }, | ||||
| @ -133,11 +135,12 @@ static struct sun4i_ss_alg_template ss_algs[] = { | ||||
| 			.cra_driver_name = "cbc-des-sun4i-ss", | ||||
| 			.cra_priority = 300, | ||||
| 			.cra_blocksize = DES_BLOCK_SIZE, | ||||
| 			.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY, | ||||
| 			.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_NEED_FALLBACK, | ||||
| 			.cra_ctxsize = sizeof(struct sun4i_req_ctx), | ||||
| 			.cra_module = THIS_MODULE, | ||||
| 			.cra_alignmask = 3, | ||||
| 			.cra_init = sun4i_ss_cipher_init, | ||||
| 			.cra_exit = sun4i_ss_cipher_exit, | ||||
| 		} | ||||
| 	} | ||||
| }, | ||||
| @ -153,11 +156,12 @@ static struct sun4i_ss_alg_template ss_algs[] = { | ||||
| 			.cra_driver_name = "ecb-des-sun4i-ss", | ||||
| 			.cra_priority = 300, | ||||
| 			.cra_blocksize = DES_BLOCK_SIZE, | ||||
| 			.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY, | ||||
| 			.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_NEED_FALLBACK, | ||||
| 			.cra_ctxsize = sizeof(struct sun4i_req_ctx), | ||||
| 			.cra_module = THIS_MODULE, | ||||
| 			.cra_alignmask = 3, | ||||
| 			.cra_init = sun4i_ss_cipher_init, | ||||
| 			.cra_exit = sun4i_ss_cipher_exit, | ||||
| 		} | ||||
| 	} | ||||
| }, | ||||
| @ -174,11 +178,12 @@ static struct sun4i_ss_alg_template ss_algs[] = { | ||||
| 			.cra_driver_name = "cbc-des3-sun4i-ss", | ||||
| 			.cra_priority = 300, | ||||
| 			.cra_blocksize = DES3_EDE_BLOCK_SIZE, | ||||
| 			.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY, | ||||
| 			.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_NEED_FALLBACK, | ||||
| 			.cra_ctxsize = sizeof(struct sun4i_req_ctx), | ||||
| 			.cra_module = THIS_MODULE, | ||||
| 			.cra_alignmask = 3, | ||||
| 			.cra_init = sun4i_ss_cipher_init, | ||||
| 			.cra_exit = sun4i_ss_cipher_exit, | ||||
| 		} | ||||
| 	} | ||||
| }, | ||||
| @ -194,10 +199,12 @@ static struct sun4i_ss_alg_template ss_algs[] = { | ||||
| 			.cra_driver_name = "ecb-des3-sun4i-ss", | ||||
| 			.cra_priority = 300, | ||||
| 			.cra_blocksize = DES3_EDE_BLOCK_SIZE, | ||||
| 			.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_NEED_FALLBACK, | ||||
| 			.cra_ctxsize = sizeof(struct sun4i_req_ctx), | ||||
| 			.cra_module = THIS_MODULE, | ||||
| 			.cra_alignmask = 3, | ||||
| 			.cra_init = sun4i_ss_cipher_init, | ||||
| 			.cra_exit = sun4i_ss_cipher_exit, | ||||
| 		} | ||||
| 	} | ||||
| }, | ||||
|  | ||||
| @ -161,6 +161,7 @@ struct sun4i_tfm_ctx { | ||||
| 	u32 keylen; | ||||
| 	u32 keymode; | ||||
| 	struct sun4i_ss_ctx *ss; | ||||
| 	struct crypto_sync_skcipher *fallback_tfm; | ||||
| }; | ||||
| 
 | ||||
| struct sun4i_cipher_req_ctx { | ||||
| @ -203,6 +204,7 @@ int sun4i_ss_ecb_des3_encrypt(struct skcipher_request *areq); | ||||
| int sun4i_ss_ecb_des3_decrypt(struct skcipher_request *areq); | ||||
| 
 | ||||
| int sun4i_ss_cipher_init(struct crypto_tfm *tfm); | ||||
| void sun4i_ss_cipher_exit(struct crypto_tfm *tfm); | ||||
| int sun4i_ss_aes_setkey(struct crypto_skcipher *tfm, const u8 *key, | ||||
| 			unsigned int keylen); | ||||
| int sun4i_ss_des_setkey(struct crypto_skcipher *tfm, const u8 *key, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user