Commit 92fec16d authored by Giovanni Cabiddu's avatar Giovanni Cabiddu Committed by Herbert Xu

crypto: qat - return proper error code in setkey

If an invalid key is provided as input to the setkey function, the
function always failed returning -ENOMEM rather than -EINVAL.
Furthermore, if setkey was called multiple times with an invalid key,
the device instance was getting leaked.

This patch fixes the error paths in the setkey functions by returning
the correct error code in case of error and freeing all the resources
allocated in this function in case of failure.

This problem was found with by the new extra run-time crypto self test.
Reviewed-by: default avatarConor Mcloughlin <conor.mcloughlin@intel.com>
Tested-by: default avatarSergey Portnoy <sergey.portnoy@intel.com>
Signed-off-by: default avatarGiovanni Cabiddu <giovanni.cabiddu@intel.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 51d33c2f
...@@ -595,45 +595,52 @@ static int qat_alg_ablkcipher_init_sessions(struct qat_alg_ablkcipher_ctx *ctx, ...@@ -595,45 +595,52 @@ static int qat_alg_ablkcipher_init_sessions(struct qat_alg_ablkcipher_ctx *ctx,
return -EINVAL; return -EINVAL;
} }
static int qat_alg_aead_setkey(struct crypto_aead *tfm, const uint8_t *key, static int qat_alg_aead_rekey(struct crypto_aead *tfm, const uint8_t *key,
unsigned int keylen) unsigned int keylen)
{ {
struct qat_alg_aead_ctx *ctx = crypto_aead_ctx(tfm); struct qat_alg_aead_ctx *ctx = crypto_aead_ctx(tfm);
struct device *dev;
if (ctx->enc_cd) {
/* rekeying */
dev = &GET_DEV(ctx->inst->accel_dev);
memset(ctx->enc_cd, 0, sizeof(*ctx->enc_cd)); memset(ctx->enc_cd, 0, sizeof(*ctx->enc_cd));
memset(ctx->dec_cd, 0, sizeof(*ctx->dec_cd)); memset(ctx->dec_cd, 0, sizeof(*ctx->dec_cd));
memset(&ctx->enc_fw_req, 0, sizeof(ctx->enc_fw_req)); memset(&ctx->enc_fw_req, 0, sizeof(ctx->enc_fw_req));
memset(&ctx->dec_fw_req, 0, sizeof(ctx->dec_fw_req)); memset(&ctx->dec_fw_req, 0, sizeof(ctx->dec_fw_req));
} else {
/* new key */ return qat_alg_aead_init_sessions(tfm, key, keylen,
ICP_QAT_HW_CIPHER_CBC_MODE);
}
static int qat_alg_aead_newkey(struct crypto_aead *tfm, const uint8_t *key,
unsigned int keylen)
{
struct qat_alg_aead_ctx *ctx = crypto_aead_ctx(tfm);
struct qat_crypto_instance *inst = NULL;
int node = get_current_node(); int node = get_current_node();
struct qat_crypto_instance *inst = struct device *dev;
qat_crypto_get_instance_node(node); int ret;
if (!inst) {
return -EINVAL;
}
inst = qat_crypto_get_instance_node(node);
if (!inst)
return -EINVAL;
dev = &GET_DEV(inst->accel_dev); dev = &GET_DEV(inst->accel_dev);
ctx->inst = inst; ctx->inst = inst;
ctx->enc_cd = dma_alloc_coherent(dev, sizeof(*ctx->enc_cd), ctx->enc_cd = dma_alloc_coherent(dev, sizeof(*ctx->enc_cd),
&ctx->enc_cd_paddr, &ctx->enc_cd_paddr,
GFP_ATOMIC); GFP_ATOMIC);
if (!ctx->enc_cd) { if (!ctx->enc_cd) {
return -ENOMEM; ret = -ENOMEM;
goto out_free_inst;
} }
ctx->dec_cd = dma_alloc_coherent(dev, sizeof(*ctx->dec_cd), ctx->dec_cd = dma_alloc_coherent(dev, sizeof(*ctx->dec_cd),
&ctx->dec_cd_paddr, &ctx->dec_cd_paddr,
GFP_ATOMIC); GFP_ATOMIC);
if (!ctx->dec_cd) { if (!ctx->dec_cd) {
ret = -ENOMEM;
goto out_free_enc; goto out_free_enc;
} }
}
if (qat_alg_aead_init_sessions(tfm, key, keylen, ret = qat_alg_aead_init_sessions(tfm, key, keylen,
ICP_QAT_HW_CIPHER_CBC_MODE)) ICP_QAT_HW_CIPHER_CBC_MODE);
if (ret)
goto out_free_all; goto out_free_all;
return 0; return 0;
...@@ -648,7 +655,21 @@ static int qat_alg_aead_setkey(struct crypto_aead *tfm, const uint8_t *key, ...@@ -648,7 +655,21 @@ static int qat_alg_aead_setkey(struct crypto_aead *tfm, const uint8_t *key,
dma_free_coherent(dev, sizeof(struct qat_alg_cd), dma_free_coherent(dev, sizeof(struct qat_alg_cd),
ctx->enc_cd, ctx->enc_cd_paddr); ctx->enc_cd, ctx->enc_cd_paddr);
ctx->enc_cd = NULL; ctx->enc_cd = NULL;
return -ENOMEM; out_free_inst:
ctx->inst = NULL;
qat_crypto_put_instance(inst);
return ret;
}
static int qat_alg_aead_setkey(struct crypto_aead *tfm, const uint8_t *key,
unsigned int keylen)
{
struct qat_alg_aead_ctx *ctx = crypto_aead_ctx(tfm);
if (ctx->enc_cd)
return qat_alg_aead_rekey(tfm, key, keylen);
else
return qat_alg_aead_newkey(tfm, key, keylen);
} }
static void qat_alg_free_bufl(struct qat_crypto_instance *inst, static void qat_alg_free_bufl(struct qat_crypto_instance *inst,
...@@ -930,42 +951,49 @@ static int qat_alg_aead_enc(struct aead_request *areq) ...@@ -930,42 +951,49 @@ static int qat_alg_aead_enc(struct aead_request *areq)
return -EINPROGRESS; return -EINPROGRESS;
} }
static int qat_alg_ablkcipher_setkey(struct crypto_ablkcipher *tfm, static int qat_alg_ablkcipher_rekey(struct qat_alg_ablkcipher_ctx *ctx,
const u8 *key, unsigned int keylen, const u8 *key, unsigned int keylen,
int mode) int mode)
{ {
struct qat_alg_ablkcipher_ctx *ctx = crypto_ablkcipher_ctx(tfm);
struct device *dev;
if (ctx->enc_cd) {
/* rekeying */
dev = &GET_DEV(ctx->inst->accel_dev);
memset(ctx->enc_cd, 0, sizeof(*ctx->enc_cd)); memset(ctx->enc_cd, 0, sizeof(*ctx->enc_cd));
memset(ctx->dec_cd, 0, sizeof(*ctx->dec_cd)); memset(ctx->dec_cd, 0, sizeof(*ctx->dec_cd));
memset(&ctx->enc_fw_req, 0, sizeof(ctx->enc_fw_req)); memset(&ctx->enc_fw_req, 0, sizeof(ctx->enc_fw_req));
memset(&ctx->dec_fw_req, 0, sizeof(ctx->dec_fw_req)); memset(&ctx->dec_fw_req, 0, sizeof(ctx->dec_fw_req));
} else {
/* new key */ return qat_alg_ablkcipher_init_sessions(ctx, key, keylen, mode);
}
static int qat_alg_ablkcipher_newkey(struct qat_alg_ablkcipher_ctx *ctx,
const u8 *key, unsigned int keylen,
int mode)
{
struct qat_crypto_instance *inst = NULL;
struct device *dev;
int node = get_current_node(); int node = get_current_node();
struct qat_crypto_instance *inst = int ret;
qat_crypto_get_instance_node(node);
inst = qat_crypto_get_instance_node(node);
if (!inst) if (!inst)
return -EINVAL; return -EINVAL;
dev = &GET_DEV(inst->accel_dev); dev = &GET_DEV(inst->accel_dev);
ctx->inst = inst; ctx->inst = inst;
ctx->enc_cd = dma_alloc_coherent(dev, sizeof(*ctx->enc_cd), ctx->enc_cd = dma_alloc_coherent(dev, sizeof(*ctx->enc_cd),
&ctx->enc_cd_paddr, &ctx->enc_cd_paddr,
GFP_ATOMIC); GFP_ATOMIC);
if (!ctx->enc_cd) if (!ctx->enc_cd) {
return -ENOMEM; ret = -ENOMEM;
goto out_free_instance;
}
ctx->dec_cd = dma_alloc_coherent(dev, sizeof(*ctx->dec_cd), ctx->dec_cd = dma_alloc_coherent(dev, sizeof(*ctx->dec_cd),
&ctx->dec_cd_paddr, &ctx->dec_cd_paddr,
GFP_ATOMIC); GFP_ATOMIC);
if (!ctx->dec_cd) if (!ctx->dec_cd) {
ret = -ENOMEM;
goto out_free_enc; goto out_free_enc;
} }
if (qat_alg_ablkcipher_init_sessions(ctx, key, keylen, mode))
ret = qat_alg_ablkcipher_init_sessions(ctx, key, keylen, mode);
if (ret)
goto out_free_all; goto out_free_all;
return 0; return 0;
...@@ -980,7 +1008,22 @@ static int qat_alg_ablkcipher_setkey(struct crypto_ablkcipher *tfm, ...@@ -980,7 +1008,22 @@ static int qat_alg_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
dma_free_coherent(dev, sizeof(*ctx->enc_cd), dma_free_coherent(dev, sizeof(*ctx->enc_cd),
ctx->enc_cd, ctx->enc_cd_paddr); ctx->enc_cd, ctx->enc_cd_paddr);
ctx->enc_cd = NULL; ctx->enc_cd = NULL;
return -ENOMEM; out_free_instance:
ctx->inst = NULL;
qat_crypto_put_instance(inst);
return ret;
}
static int qat_alg_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
const u8 *key, unsigned int keylen,
int mode)
{
struct qat_alg_ablkcipher_ctx *ctx = crypto_ablkcipher_ctx(tfm);
if (ctx->enc_cd)
return qat_alg_ablkcipher_rekey(ctx, key, keylen, mode);
else
return qat_alg_ablkcipher_newkey(ctx, key, keylen, mode);
} }
static int qat_alg_ablkcipher_cbc_setkey(struct crypto_ablkcipher *tfm, static int qat_alg_ablkcipher_cbc_setkey(struct crypto_ablkcipher *tfm,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment