diff options
Diffstat (limited to 'drivers/crypto/qce/skcipher.c')
| -rw-r--r-- | drivers/crypto/qce/skcipher.c | 69 | 
1 files changed, 60 insertions, 9 deletions
| diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c index a2d3da0ad95f..c0a0d8c4fce1 100644 --- a/drivers/crypto/qce/skcipher.c +++ b/drivers/crypto/qce/skcipher.c @@ -8,6 +8,7 @@  #include <linux/interrupt.h>  #include <linux/moduleparam.h>  #include <linux/types.h> +#include <linux/errno.h>  #include <crypto/aes.h>  #include <crypto/internal/des.h>  #include <crypto/internal/skcipher.h> @@ -143,7 +144,7 @@ qce_skcipher_async_req_handle(struct crypto_async_request *async_req)  	qce_dma_issue_pending(&qce->dma); -	ret = qce_start(async_req, tmpl->crypto_alg_type, req->cryptlen, 0); +	ret = qce_start(async_req, tmpl->crypto_alg_type);  	if (ret)  		goto error_terminate; @@ -167,16 +168,33 @@ static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key,  	struct crypto_tfm *tfm = crypto_skcipher_tfm(ablk);  	struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);  	unsigned long flags = to_cipher_tmpl(ablk)->alg_flags; +	unsigned int __keylen;  	int ret;  	if (!key || !keylen)  		return -EINVAL; -	switch (IS_XTS(flags) ? keylen >> 1 : keylen) { +	/* +	 * AES XTS key1 = key2 not supported by crypto engine. +	 * Revisit to request a fallback cipher in this case. +	 */ +	if (IS_XTS(flags)) { +		__keylen = keylen >> 1; +		if (!memcmp(key, key + __keylen, __keylen)) +			return -ENOKEY; +	} else { +		__keylen = keylen; +	} + +	switch (__keylen) {  	case AES_KEYSIZE_128:  	case AES_KEYSIZE_256:  		memcpy(ctx->enc_key, key, keylen);  		break; +	case AES_KEYSIZE_192: +		break; +	default: +		return -EINVAL;  	}  	ret = crypto_skcipher_setkey(ctx->fallback, key, keylen); @@ -204,12 +222,27 @@ static int qce_des3_setkey(struct crypto_skcipher *ablk, const u8 *key,  			   unsigned int keylen)  {  	struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); +	u32 _key[6];  	int err;  	err = verify_skcipher_des3_key(ablk, key);  	if (err)  		return err; +	/* +	 * The crypto engine does not support any two keys +	 * being the same for triple des algorithms. The +	 * verify_skcipher_des3_key does not check for all the +	 * below conditions. Return -ENOKEY in case any two keys +	 * are the same. Revisit to see if a fallback cipher +	 * is needed to handle this condition. +	 */ +	memcpy(_key, key, DES3_EDE_KEY_SIZE); +	if (!((_key[0] ^ _key[2]) | (_key[1] ^ _key[3])) || +	    !((_key[2] ^ _key[4]) | (_key[3] ^ _key[5])) || +	    !((_key[0] ^ _key[4]) | (_key[1] ^ _key[5]))) +		return -ENOKEY; +  	ctx->enc_keylen = keylen;  	memcpy(ctx->enc_key, key, keylen);  	return 0; @@ -221,6 +254,7 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt)  	struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);  	struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req);  	struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); +	unsigned int blocksize = crypto_skcipher_blocksize(tfm);  	int keylen;  	int ret; @@ -228,14 +262,31 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt)  	rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT;  	keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; -	/* qce is hanging when AES-XTS request len > QCE_SECTOR_SIZE and -	 * is not a multiple of it; pass such requests to the fallback +	/* CE does not handle 0 length messages */ +	if (!req->cryptlen) +		return 0; + +	/* +	 * ECB and CBC algorithms require message lengths to be +	 * multiples of block size. +	 */ +	if (IS_ECB(rctx->flags) || IS_CBC(rctx->flags)) +		if (!IS_ALIGNED(req->cryptlen, blocksize)) +			return -EINVAL; + +	/* +	 * Conditions for requesting a fallback cipher +	 * AES-192 (not supported by crypto engine (CE)) +	 * AES-XTS request with len <= 512 byte (not recommended to use CE) +	 * AES-XTS request with len > QCE_SECTOR_SIZE and +	 * is not a multiple of it.(Revisit this condition to check if it is +	 * needed in all versions of CE)  	 */  	if (IS_AES(rctx->flags) && -	    (((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || -	      req->cryptlen <= aes_sw_max_len) || -	     (IS_XTS(rctx->flags) && req->cryptlen > QCE_SECTOR_SIZE && -	      req->cryptlen % QCE_SECTOR_SIZE))) { +	    ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || +	    (IS_XTS(rctx->flags) && ((req->cryptlen <= aes_sw_max_len) || +	    (req->cryptlen > QCE_SECTOR_SIZE && +	    req->cryptlen % QCE_SECTOR_SIZE))))) {  		skcipher_request_set_tfm(&rctx->fallback_req, ctx->fallback);  		skcipher_request_set_callback(&rctx->fallback_req,  					      req->base.flags, @@ -307,7 +358,7 @@ static const struct qce_skcipher_def skcipher_def[] = {  		.name		= "ecb(aes)",  		.drv_name	= "ecb-aes-qce",  		.blocksize	= AES_BLOCK_SIZE, -		.ivsize		= AES_BLOCK_SIZE, +		.ivsize		= 0,  		.min_keysize	= AES_MIN_KEY_SIZE,  		.max_keysize	= AES_MAX_KEY_SIZE,  	}, | 
