Commit 7ccb750d authored by Herbert Xu's avatar Herbert Xu
Browse files

crypto: octeontx2 - Fix authenc setkey



Use the generic crypto_authenc_extractkeys helper instead of custom
parsing code that is slightly broken.  Also fix a number of memory
leaks by moving memory allocation from setkey to init_tfm (setkey
can be called multiple times over the life of a tfm).

Finally accept all hash key lengths by running the digest over
extra-long keys.

Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 311eea7e
Loading
Loading
Loading
Loading
+90 −164
Original line number Diff line number Diff line
@@ -11,7 +11,6 @@
#include <crypto/xts.h>
#include <crypto/gcm.h>
#include <crypto/scatterwalk.h>
#include <linux/rtnetlink.h>
#include <linux/sort.h>
#include <linux/module.h>
#include "otx2_cptvf.h"
@@ -55,6 +54,8 @@ static struct cpt_device_table se_devices = {
	.count = ATOMIC_INIT(0)
};

static struct otx2_cpt_sdesc *alloc_sdesc(struct crypto_shash *alg);

static inline int get_se_device(struct pci_dev **pdev, int *cpu_num)
{
	int count;
@@ -598,40 +599,56 @@ static int cpt_aead_init(struct crypto_aead *atfm, u8 cipher_type, u8 mac_type)
	ctx->cipher_type = cipher_type;
	ctx->mac_type = mac_type;

	/*
	 * When selected cipher is NULL we use HMAC opcode instead of
	 * FLEXICRYPTO opcode therefore we don't need to use HASH algorithms
	 * for calculating ipad and opad
	 */
	if (ctx->cipher_type != OTX2_CPT_CIPHER_NULL) {
	switch (ctx->mac_type) {
	case OTX2_CPT_SHA1:
			ctx->hashalg = crypto_alloc_shash("sha1", 0,
							  CRYPTO_ALG_ASYNC);
			if (IS_ERR(ctx->hashalg))
				return PTR_ERR(ctx->hashalg);
		ctx->hashalg = crypto_alloc_shash("sha1", 0, 0);
		break;

	case OTX2_CPT_SHA256:
			ctx->hashalg = crypto_alloc_shash("sha256", 0,
							  CRYPTO_ALG_ASYNC);
			if (IS_ERR(ctx->hashalg))
				return PTR_ERR(ctx->hashalg);
		ctx->hashalg = crypto_alloc_shash("sha256", 0, 0);
		break;

	case OTX2_CPT_SHA384:
			ctx->hashalg = crypto_alloc_shash("sha384", 0,
							  CRYPTO_ALG_ASYNC);
			if (IS_ERR(ctx->hashalg))
				return PTR_ERR(ctx->hashalg);
		ctx->hashalg = crypto_alloc_shash("sha384", 0, 0);
		break;

	case OTX2_CPT_SHA512:
			ctx->hashalg = crypto_alloc_shash("sha512", 0,
							  CRYPTO_ALG_ASYNC);
		ctx->hashalg = crypto_alloc_shash("sha512", 0, 0);
		break;
	}

	if (IS_ERR(ctx->hashalg))
		return PTR_ERR(ctx->hashalg);
			break;

	if (ctx->hashalg) {
		ctx->sdesc = alloc_sdesc(ctx->hashalg);
		if (!ctx->sdesc) {
			crypto_free_shash(ctx->hashalg);
			return -ENOMEM;
		}
	}

	/*
	 * When selected cipher is NULL we use HMAC opcode instead of
	 * FLEXICRYPTO opcode therefore we don't need to use HASH algorithms
	 * for calculating ipad and opad
	 */
	if (ctx->cipher_type != OTX2_CPT_CIPHER_NULL && ctx->hashalg) {
		int ss = crypto_shash_statesize(ctx->hashalg);

		ctx->ipad = kzalloc(ss, GFP_KERNEL);
		if (!ctx->ipad) {
			kfree(ctx->sdesc);
			crypto_free_shash(ctx->hashalg);
			return -ENOMEM;
		}

		ctx->opad = kzalloc(ss, GFP_KERNEL);
		if (!ctx->opad) {
			kfree(ctx->ipad);
			kfree(ctx->sdesc);
			crypto_free_shash(ctx->hashalg);
			return -ENOMEM;
		}
	}
	switch (ctx->cipher_type) {
@@ -713,7 +730,6 @@ static void otx2_cpt_aead_exit(struct crypto_aead *tfm)

	kfree(ctx->ipad);
	kfree(ctx->opad);
	if (ctx->hashalg)
	crypto_free_shash(ctx->hashalg);
	kfree(ctx->sdesc);

@@ -788,7 +804,7 @@ static inline void swap_data64(void *buf, u32 len)
		cpu_to_be64s(src);
}

static int copy_pad(u8 mac_type, u8 *out_pad, u8 *in_pad)
static int swap_pad(u8 mac_type, u8 *pad)
{
	struct sha512_state *sha512;
	struct sha256_state *sha256;
@@ -796,22 +812,19 @@ static int copy_pad(u8 mac_type, u8 *out_pad, u8 *in_pad)

	switch (mac_type) {
	case OTX2_CPT_SHA1:
		sha1 = (struct sha1_state *) in_pad;
		sha1 = (struct sha1_state *)pad;
		swap_data32(sha1->state, SHA1_DIGEST_SIZE);
		memcpy(out_pad, &sha1->state, SHA1_DIGEST_SIZE);
		break;

	case OTX2_CPT_SHA256:
		sha256 = (struct sha256_state *) in_pad;
		sha256 = (struct sha256_state *)pad;
		swap_data32(sha256->state, SHA256_DIGEST_SIZE);
		memcpy(out_pad, &sha256->state, SHA256_DIGEST_SIZE);
		break;

	case OTX2_CPT_SHA384:
	case OTX2_CPT_SHA512:
		sha512 = (struct sha512_state *) in_pad;
		sha512 = (struct sha512_state *)pad;
		swap_data64(sha512->state, SHA512_DIGEST_SIZE);
		memcpy(out_pad, &sha512->state, SHA512_DIGEST_SIZE);
		break;

	default:
@@ -821,55 +834,54 @@ static int copy_pad(u8 mac_type, u8 *out_pad, u8 *in_pad)
	return 0;
}

static int aead_hmac_init(struct crypto_aead *cipher)
static int aead_hmac_init(struct crypto_aead *cipher,
			  struct crypto_authenc_keys *keys)
{
	struct otx2_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(cipher);
	int state_size = crypto_shash_statesize(ctx->hashalg);
	int ds = crypto_shash_digestsize(ctx->hashalg);
	int bs = crypto_shash_blocksize(ctx->hashalg);
	int authkeylen = ctx->auth_key_len;
	int authkeylen = keys->authkeylen;
	u8 *ipad = NULL, *opad = NULL;
	int ret = 0, icount = 0;

	ctx->sdesc = alloc_sdesc(ctx->hashalg);
	if (!ctx->sdesc)
		return -ENOMEM;
	int icount = 0;
	int ret;

	ctx->ipad = kzalloc(bs, GFP_KERNEL);
	if (!ctx->ipad) {
		ret = -ENOMEM;
	if (authkeylen > bs) {
		ret = crypto_shash_digest(&ctx->sdesc->shash, keys->authkey,
					  authkeylen, ctx->key);
		if (ret)
			goto calc_fail;
	}

	ctx->opad = kzalloc(bs, GFP_KERNEL);
	if (!ctx->opad) {
		ret = -ENOMEM;
		goto calc_fail;
	}
		authkeylen = ds;
	} else
		memcpy(ctx->key, keys->authkey, authkeylen);

	ipad = kzalloc(state_size, GFP_KERNEL);
	if (!ipad) {
		ret = -ENOMEM;
		goto calc_fail;
	}
	ctx->enc_key_len = keys->enckeylen;
	ctx->auth_key_len = authkeylen;

	opad = kzalloc(state_size, GFP_KERNEL);
	if (!opad) {
		ret = -ENOMEM;
		goto calc_fail;
	if (ctx->cipher_type == OTX2_CPT_CIPHER_NULL)
		return keys->enckeylen ? -EINVAL : 0;

	switch (keys->enckeylen) {
	case AES_KEYSIZE_128:
		ctx->key_type = OTX2_CPT_AES_128_BIT;
		break;
	case AES_KEYSIZE_192:
		ctx->key_type = OTX2_CPT_AES_192_BIT;
		break;
	case AES_KEYSIZE_256:
		ctx->key_type = OTX2_CPT_AES_256_BIT;
		break;
	default:
		/* Invalid key length */
		return -EINVAL;
	}

	if (authkeylen > bs) {
		ret = crypto_shash_digest(&ctx->sdesc->shash, ctx->key,
					  authkeylen, ipad);
		if (ret)
			goto calc_fail;
	memcpy(ctx->key + authkeylen, keys->enckey, keys->enckeylen);

		authkeylen = ds;
	} else {
		memcpy(ipad, ctx->key, authkeylen);
	}
	ipad = ctx->ipad;
	opad = ctx->opad;

	memcpy(ipad, ctx->key, authkeylen);
	memset(ipad + authkeylen, 0, bs - authkeylen);
	memcpy(opad, ipad, bs);

@@ -887,7 +899,7 @@ static int aead_hmac_init(struct crypto_aead *cipher)
	crypto_shash_init(&ctx->sdesc->shash);
	crypto_shash_update(&ctx->sdesc->shash, ipad, bs);
	crypto_shash_export(&ctx->sdesc->shash, ipad);
	ret = copy_pad(ctx->mac_type, ctx->ipad, ipad);
	ret = swap_pad(ctx->mac_type, ipad);
	if (ret)
		goto calc_fail;

@@ -895,25 +907,9 @@ static int aead_hmac_init(struct crypto_aead *cipher)
	crypto_shash_init(&ctx->sdesc->shash);
	crypto_shash_update(&ctx->sdesc->shash, opad, bs);
	crypto_shash_export(&ctx->sdesc->shash, opad);
	ret = copy_pad(ctx->mac_type, ctx->opad, opad);
	if (ret)
		goto calc_fail;

	kfree(ipad);
	kfree(opad);

	return 0;
	ret = swap_pad(ctx->mac_type, opad);

calc_fail:
	kfree(ctx->ipad);
	ctx->ipad = NULL;
	kfree(ctx->opad);
	ctx->opad = NULL;
	kfree(ipad);
	kfree(opad);
	kfree(ctx->sdesc);
	ctx->sdesc = NULL;

	return ret;
}

@@ -921,87 +917,17 @@ static int otx2_cpt_aead_cbc_aes_sha_setkey(struct crypto_aead *cipher,
					    const unsigned char *key,
					    unsigned int keylen)
{
	struct otx2_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(cipher);
	struct crypto_authenc_key_param *param;
	int enckeylen = 0, authkeylen = 0;
	struct rtattr *rta = (void *)key;

	if (!RTA_OK(rta, keylen))
		return -EINVAL;

	if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
		return -EINVAL;

	if (RTA_PAYLOAD(rta) < sizeof(*param))
		return -EINVAL;

	param = RTA_DATA(rta);
	enckeylen = be32_to_cpu(param->enckeylen);
	key += RTA_ALIGN(rta->rta_len);
	keylen -= RTA_ALIGN(rta->rta_len);
	if (keylen < enckeylen)
		return -EINVAL;

	if (keylen > OTX2_CPT_MAX_KEY_SIZE)
		return -EINVAL;
	struct crypto_authenc_keys authenc_keys;

	authkeylen = keylen - enckeylen;
	memcpy(ctx->key, key, keylen);

	switch (enckeylen) {
	case AES_KEYSIZE_128:
		ctx->key_type = OTX2_CPT_AES_128_BIT;
		break;
	case AES_KEYSIZE_192:
		ctx->key_type = OTX2_CPT_AES_192_BIT;
		break;
	case AES_KEYSIZE_256:
		ctx->key_type = OTX2_CPT_AES_256_BIT;
		break;
	default:
		/* Invalid key length */
		return -EINVAL;
	}

	ctx->enc_key_len = enckeylen;
	ctx->auth_key_len = authkeylen;

	return aead_hmac_init(cipher);
	return crypto_authenc_extractkeys(&authenc_keys, key, keylen) ?:
	       aead_hmac_init(cipher, &authenc_keys);
}

static int otx2_cpt_aead_ecb_null_sha_setkey(struct crypto_aead *cipher,
					     const unsigned char *key,
					     unsigned int keylen)
{
	struct otx2_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(cipher);
	struct crypto_authenc_key_param *param;
	struct rtattr *rta = (void *)key;
	int enckeylen = 0;

	if (!RTA_OK(rta, keylen))
		return -EINVAL;

	if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
		return -EINVAL;

	if (RTA_PAYLOAD(rta) < sizeof(*param))
		return -EINVAL;

	param = RTA_DATA(rta);
	enckeylen = be32_to_cpu(param->enckeylen);
	key += RTA_ALIGN(rta->rta_len);
	keylen -= RTA_ALIGN(rta->rta_len);
	if (enckeylen != 0)
		return -EINVAL;

	if (keylen > OTX2_CPT_MAX_KEY_SIZE)
		return -EINVAL;

	memcpy(ctx->key, key, keylen);
	ctx->enc_key_len = enckeylen;
	ctx->auth_key_len = keylen;

	return 0;
	return otx2_cpt_aead_cbc_aes_sha_setkey(cipher, key, keylen);
}

static int otx2_cpt_aead_gcm_aes_setkey(struct crypto_aead *cipher,