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: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
parent
311eea7e37
commit
7ccb750dca
@ -11,7 +11,6 @@
|
|||||||
#include <crypto/xts.h>
|
#include <crypto/xts.h>
|
||||||
#include <crypto/gcm.h>
|
#include <crypto/gcm.h>
|
||||||
#include <crypto/scatterwalk.h>
|
#include <crypto/scatterwalk.h>
|
||||||
#include <linux/rtnetlink.h>
|
|
||||||
#include <linux/sort.h>
|
#include <linux/sort.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include "otx2_cptvf.h"
|
#include "otx2_cptvf.h"
|
||||||
@ -55,6 +54,8 @@ static struct cpt_device_table se_devices = {
|
|||||||
.count = ATOMIC_INIT(0)
|
.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)
|
static inline int get_se_device(struct pci_dev **pdev, int *cpu_num)
|
||||||
{
|
{
|
||||||
int count;
|
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->cipher_type = cipher_type;
|
||||||
ctx->mac_type = mac_type;
|
ctx->mac_type = mac_type;
|
||||||
|
|
||||||
|
switch (ctx->mac_type) {
|
||||||
|
case OTX2_CPT_SHA1:
|
||||||
|
ctx->hashalg = crypto_alloc_shash("sha1", 0, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OTX2_CPT_SHA256:
|
||||||
|
ctx->hashalg = crypto_alloc_shash("sha256", 0, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OTX2_CPT_SHA384:
|
||||||
|
ctx->hashalg = crypto_alloc_shash("sha384", 0, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OTX2_CPT_SHA512:
|
||||||
|
ctx->hashalg = crypto_alloc_shash("sha512", 0, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ERR(ctx->hashalg))
|
||||||
|
return PTR_ERR(ctx->hashalg);
|
||||||
|
|
||||||
|
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
|
* When selected cipher is NULL we use HMAC opcode instead of
|
||||||
* FLEXICRYPTO opcode therefore we don't need to use HASH algorithms
|
* FLEXICRYPTO opcode therefore we don't need to use HASH algorithms
|
||||||
* for calculating ipad and opad
|
* for calculating ipad and opad
|
||||||
*/
|
*/
|
||||||
if (ctx->cipher_type != OTX2_CPT_CIPHER_NULL) {
|
if (ctx->cipher_type != OTX2_CPT_CIPHER_NULL && ctx->hashalg) {
|
||||||
switch (ctx->mac_type) {
|
int ss = crypto_shash_statesize(ctx->hashalg);
|
||||||
case OTX2_CPT_SHA1:
|
|
||||||
ctx->hashalg = crypto_alloc_shash("sha1", 0,
|
|
||||||
CRYPTO_ALG_ASYNC);
|
|
||||||
if (IS_ERR(ctx->hashalg))
|
|
||||||
return PTR_ERR(ctx->hashalg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OTX2_CPT_SHA256:
|
ctx->ipad = kzalloc(ss, GFP_KERNEL);
|
||||||
ctx->hashalg = crypto_alloc_shash("sha256", 0,
|
if (!ctx->ipad) {
|
||||||
CRYPTO_ALG_ASYNC);
|
kfree(ctx->sdesc);
|
||||||
if (IS_ERR(ctx->hashalg))
|
crypto_free_shash(ctx->hashalg);
|
||||||
return PTR_ERR(ctx->hashalg);
|
return -ENOMEM;
|
||||||
break;
|
}
|
||||||
|
|
||||||
case OTX2_CPT_SHA384:
|
ctx->opad = kzalloc(ss, GFP_KERNEL);
|
||||||
ctx->hashalg = crypto_alloc_shash("sha384", 0,
|
if (!ctx->opad) {
|
||||||
CRYPTO_ALG_ASYNC);
|
kfree(ctx->ipad);
|
||||||
if (IS_ERR(ctx->hashalg))
|
kfree(ctx->sdesc);
|
||||||
return PTR_ERR(ctx->hashalg);
|
crypto_free_shash(ctx->hashalg);
|
||||||
break;
|
return -ENOMEM;
|
||||||
|
|
||||||
case OTX2_CPT_SHA512:
|
|
||||||
ctx->hashalg = crypto_alloc_shash("sha512", 0,
|
|
||||||
CRYPTO_ALG_ASYNC);
|
|
||||||
if (IS_ERR(ctx->hashalg))
|
|
||||||
return PTR_ERR(ctx->hashalg);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (ctx->cipher_type) {
|
switch (ctx->cipher_type) {
|
||||||
@ -713,7 +730,6 @@ static void otx2_cpt_aead_exit(struct crypto_aead *tfm)
|
|||||||
|
|
||||||
kfree(ctx->ipad);
|
kfree(ctx->ipad);
|
||||||
kfree(ctx->opad);
|
kfree(ctx->opad);
|
||||||
if (ctx->hashalg)
|
|
||||||
crypto_free_shash(ctx->hashalg);
|
crypto_free_shash(ctx->hashalg);
|
||||||
kfree(ctx->sdesc);
|
kfree(ctx->sdesc);
|
||||||
|
|
||||||
@ -788,7 +804,7 @@ static inline void swap_data64(void *buf, u32 len)
|
|||||||
cpu_to_be64s(src);
|
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 sha512_state *sha512;
|
||||||
struct sha256_state *sha256;
|
struct sha256_state *sha256;
|
||||||
@ -796,22 +812,19 @@ static int copy_pad(u8 mac_type, u8 *out_pad, u8 *in_pad)
|
|||||||
|
|
||||||
switch (mac_type) {
|
switch (mac_type) {
|
||||||
case OTX2_CPT_SHA1:
|
case OTX2_CPT_SHA1:
|
||||||
sha1 = (struct sha1_state *) in_pad;
|
sha1 = (struct sha1_state *)pad;
|
||||||
swap_data32(sha1->state, SHA1_DIGEST_SIZE);
|
swap_data32(sha1->state, SHA1_DIGEST_SIZE);
|
||||||
memcpy(out_pad, &sha1->state, SHA1_DIGEST_SIZE);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OTX2_CPT_SHA256:
|
case OTX2_CPT_SHA256:
|
||||||
sha256 = (struct sha256_state *) in_pad;
|
sha256 = (struct sha256_state *)pad;
|
||||||
swap_data32(sha256->state, SHA256_DIGEST_SIZE);
|
swap_data32(sha256->state, SHA256_DIGEST_SIZE);
|
||||||
memcpy(out_pad, &sha256->state, SHA256_DIGEST_SIZE);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OTX2_CPT_SHA384:
|
case OTX2_CPT_SHA384:
|
||||||
case OTX2_CPT_SHA512:
|
case OTX2_CPT_SHA512:
|
||||||
sha512 = (struct sha512_state *) in_pad;
|
sha512 = (struct sha512_state *)pad;
|
||||||
swap_data64(sha512->state, SHA512_DIGEST_SIZE);
|
swap_data64(sha512->state, SHA512_DIGEST_SIZE);
|
||||||
memcpy(out_pad, &sha512->state, SHA512_DIGEST_SIZE);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -821,55 +834,54 @@ static int copy_pad(u8 mac_type, u8 *out_pad, u8 *in_pad)
|
|||||||
return 0;
|
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);
|
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 ds = crypto_shash_digestsize(ctx->hashalg);
|
||||||
int bs = crypto_shash_blocksize(ctx->hashalg);
|
int bs = crypto_shash_blocksize(ctx->hashalg);
|
||||||
int authkeylen = ctx->auth_key_len;
|
int authkeylen = keys->authkeylen;
|
||||||
u8 *ipad = NULL, *opad = NULL;
|
u8 *ipad = NULL, *opad = NULL;
|
||||||
int ret = 0, icount = 0;
|
int icount = 0;
|
||||||
|
int ret;
|
||||||
ctx->sdesc = alloc_sdesc(ctx->hashalg);
|
|
||||||
if (!ctx->sdesc)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
ctx->ipad = kzalloc(bs, GFP_KERNEL);
|
|
||||||
if (!ctx->ipad) {
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto calc_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->opad = kzalloc(bs, GFP_KERNEL);
|
|
||||||
if (!ctx->opad) {
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto calc_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
ipad = kzalloc(state_size, GFP_KERNEL);
|
|
||||||
if (!ipad) {
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto calc_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
opad = kzalloc(state_size, GFP_KERNEL);
|
|
||||||
if (!opad) {
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto calc_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (authkeylen > bs) {
|
if (authkeylen > bs) {
|
||||||
ret = crypto_shash_digest(&ctx->sdesc->shash, ctx->key,
|
ret = crypto_shash_digest(&ctx->sdesc->shash, keys->authkey,
|
||||||
authkeylen, ipad);
|
authkeylen, ctx->key);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto calc_fail;
|
goto calc_fail;
|
||||||
|
|
||||||
authkeylen = ds;
|
authkeylen = ds;
|
||||||
} else {
|
} else
|
||||||
memcpy(ipad, ctx->key, authkeylen);
|
memcpy(ctx->key, keys->authkey, authkeylen);
|
||||||
|
|
||||||
|
ctx->enc_key_len = keys->enckeylen;
|
||||||
|
ctx->auth_key_len = authkeylen;
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(ctx->key + authkeylen, keys->enckey, keys->enckeylen);
|
||||||
|
|
||||||
|
ipad = ctx->ipad;
|
||||||
|
opad = ctx->opad;
|
||||||
|
|
||||||
|
memcpy(ipad, ctx->key, authkeylen);
|
||||||
memset(ipad + authkeylen, 0, bs - authkeylen);
|
memset(ipad + authkeylen, 0, bs - authkeylen);
|
||||||
memcpy(opad, ipad, bs);
|
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_init(&ctx->sdesc->shash);
|
||||||
crypto_shash_update(&ctx->sdesc->shash, ipad, bs);
|
crypto_shash_update(&ctx->sdesc->shash, ipad, bs);
|
||||||
crypto_shash_export(&ctx->sdesc->shash, ipad);
|
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)
|
if (ret)
|
||||||
goto calc_fail;
|
goto calc_fail;
|
||||||
|
|
||||||
@ -895,25 +907,9 @@ static int aead_hmac_init(struct crypto_aead *cipher)
|
|||||||
crypto_shash_init(&ctx->sdesc->shash);
|
crypto_shash_init(&ctx->sdesc->shash);
|
||||||
crypto_shash_update(&ctx->sdesc->shash, opad, bs);
|
crypto_shash_update(&ctx->sdesc->shash, opad, bs);
|
||||||
crypto_shash_export(&ctx->sdesc->shash, opad);
|
crypto_shash_export(&ctx->sdesc->shash, opad);
|
||||||
ret = copy_pad(ctx->mac_type, ctx->opad, opad);
|
ret = swap_pad(ctx->mac_type, opad);
|
||||||
if (ret)
|
|
||||||
goto calc_fail;
|
|
||||||
|
|
||||||
kfree(ipad);
|
|
||||||
kfree(opad);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
calc_fail:
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -921,87 +917,17 @@ static int otx2_cpt_aead_cbc_aes_sha_setkey(struct crypto_aead *cipher,
|
|||||||
const unsigned char *key,
|
const unsigned char *key,
|
||||||
unsigned int keylen)
|
unsigned int keylen)
|
||||||
{
|
{
|
||||||
struct otx2_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(cipher);
|
struct crypto_authenc_keys authenc_keys;
|
||||||
struct crypto_authenc_key_param *param;
|
|
||||||
int enckeylen = 0, authkeylen = 0;
|
|
||||||
struct rtattr *rta = (void *)key;
|
|
||||||
|
|
||||||
if (!RTA_OK(rta, keylen))
|
return crypto_authenc_extractkeys(&authenc_keys, key, keylen) ?:
|
||||||
return -EINVAL;
|
aead_hmac_init(cipher, &authenc_keys);
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int otx2_cpt_aead_ecb_null_sha_setkey(struct crypto_aead *cipher,
|
static int otx2_cpt_aead_ecb_null_sha_setkey(struct crypto_aead *cipher,
|
||||||
const unsigned char *key,
|
const unsigned char *key,
|
||||||
unsigned int keylen)
|
unsigned int keylen)
|
||||||
{
|
{
|
||||||
struct otx2_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(cipher);
|
return otx2_cpt_aead_cbc_aes_sha_setkey(cipher, key, keylen);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int otx2_cpt_aead_gcm_aes_setkey(struct crypto_aead *cipher,
|
static int otx2_cpt_aead_gcm_aes_setkey(struct crypto_aead *cipher,
|
||||||
|
Loading…
Reference in New Issue
Block a user