Commit ced0a170 authored by Nagadheeraj Rottela's avatar Nagadheeraj Rottela Committed by Herbert Xu

crypto: cavium/nitrox - Fix cbc ciphers self test failures

Self test failures are due to wrong output IV. This patch fixes this
issue by copying back output IV into skcipher request.
Signed-off-by: default avatarNagadheeraj Rottela <rnagadheeraj@marvell.com>
Reviewed-by: default avatarSrikanth Jampala <jsrikanth@marvell.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 3fed9baa
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#define PENDING_SIG 0xFFFFFFFFFFFFFFFFUL #define PENDING_SIG 0xFFFFFFFFFFFFFFFFUL
#define PRIO 4001 #define PRIO 4001
typedef void (*sereq_completion_t)(void *req, int err);
/** /**
* struct gphdr - General purpose Header * struct gphdr - General purpose Header
* @param0: first parameter. * @param0: first parameter.
...@@ -203,12 +205,14 @@ struct nitrox_crypto_ctx { ...@@ -203,12 +205,14 @@ struct nitrox_crypto_ctx {
struct flexi_crypto_context *fctx; struct flexi_crypto_context *fctx;
} u; } u;
struct crypto_ctx_hdr *chdr; struct crypto_ctx_hdr *chdr;
sereq_completion_t callback;
}; };
struct nitrox_kcrypt_request { struct nitrox_kcrypt_request {
struct se_crypto_request creq; struct se_crypto_request creq;
u8 *src; u8 *src;
u8 *dst; u8 *dst;
u8 *iv_out;
}; };
/** /**
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <crypto/aes.h> #include <crypto/aes.h>
#include <crypto/skcipher.h> #include <crypto/skcipher.h>
#include <crypto/scatterwalk.h>
#include <crypto/ctr.h> #include <crypto/ctr.h>
#include <crypto/internal/des.h> #include <crypto/internal/des.h>
#include <crypto/xts.h> #include <crypto/xts.h>
...@@ -47,6 +48,63 @@ static enum flexi_cipher flexi_cipher_type(const char *name) ...@@ -47,6 +48,63 @@ static enum flexi_cipher flexi_cipher_type(const char *name)
return cipher->value; return cipher->value;
} }
static void free_src_sglist(struct skcipher_request *skreq)
{
struct nitrox_kcrypt_request *nkreq = skcipher_request_ctx(skreq);
kfree(nkreq->src);
}
static void free_dst_sglist(struct skcipher_request *skreq)
{
struct nitrox_kcrypt_request *nkreq = skcipher_request_ctx(skreq);
kfree(nkreq->dst);
}
static void nitrox_skcipher_callback(void *arg, int err)
{
struct skcipher_request *skreq = arg;
free_src_sglist(skreq);
free_dst_sglist(skreq);
if (err) {
pr_err_ratelimited("request failed status 0x%0x\n", err);
err = -EINVAL;
}
skcipher_request_complete(skreq, err);
}
static void nitrox_cbc_cipher_callback(void *arg, int err)
{
struct skcipher_request *skreq = arg;
struct nitrox_kcrypt_request *nkreq = skcipher_request_ctx(skreq);
struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(skreq);
int ivsize = crypto_skcipher_ivsize(cipher);
unsigned int start = skreq->cryptlen - ivsize;
if (err) {
nitrox_skcipher_callback(arg, err);
return;
}
if (nkreq->creq.ctrl.s.arg == ENCRYPT) {
scatterwalk_map_and_copy(skreq->iv, skreq->dst, start, ivsize,
0);
} else {
if (skreq->src != skreq->dst) {
scatterwalk_map_and_copy(skreq->iv, skreq->src, start,
ivsize, 0);
} else {
memcpy(skreq->iv, nkreq->iv_out, ivsize);
kfree(nkreq->iv_out);
}
}
nitrox_skcipher_callback(arg, err);
}
static int nitrox_skcipher_init(struct crypto_skcipher *tfm) static int nitrox_skcipher_init(struct crypto_skcipher *tfm)
{ {
struct nitrox_crypto_ctx *nctx = crypto_skcipher_ctx(tfm); struct nitrox_crypto_ctx *nctx = crypto_skcipher_ctx(tfm);
...@@ -63,6 +121,8 @@ static int nitrox_skcipher_init(struct crypto_skcipher *tfm) ...@@ -63,6 +121,8 @@ static int nitrox_skcipher_init(struct crypto_skcipher *tfm)
nitrox_put_device(nctx->ndev); nitrox_put_device(nctx->ndev);
return -ENOMEM; return -ENOMEM;
} }
nctx->callback = nitrox_skcipher_callback;
nctx->chdr = chdr; nctx->chdr = chdr;
nctx->u.ctx_handle = (uintptr_t)((u8 *)chdr->vaddr + nctx->u.ctx_handle = (uintptr_t)((u8 *)chdr->vaddr +
sizeof(struct ctx_hdr)); sizeof(struct ctx_hdr));
...@@ -71,6 +131,19 @@ static int nitrox_skcipher_init(struct crypto_skcipher *tfm) ...@@ -71,6 +131,19 @@ static int nitrox_skcipher_init(struct crypto_skcipher *tfm)
return 0; return 0;
} }
static int nitrox_cbc_init(struct crypto_skcipher *tfm)
{
int err;
struct nitrox_crypto_ctx *nctx = crypto_skcipher_ctx(tfm);
err = nitrox_skcipher_init(tfm);
if (err)
return err;
nctx->callback = nitrox_cbc_cipher_callback;
return 0;
}
static void nitrox_skcipher_exit(struct crypto_skcipher *tfm) static void nitrox_skcipher_exit(struct crypto_skcipher *tfm)
{ {
struct nitrox_crypto_ctx *nctx = crypto_skcipher_ctx(tfm); struct nitrox_crypto_ctx *nctx = crypto_skcipher_ctx(tfm);
...@@ -173,34 +246,6 @@ static int alloc_dst_sglist(struct skcipher_request *skreq, int ivsize) ...@@ -173,34 +246,6 @@ static int alloc_dst_sglist(struct skcipher_request *skreq, int ivsize)
return 0; return 0;
} }
static void free_src_sglist(struct skcipher_request *skreq)
{
struct nitrox_kcrypt_request *nkreq = skcipher_request_ctx(skreq);
kfree(nkreq->src);
}
static void free_dst_sglist(struct skcipher_request *skreq)
{
struct nitrox_kcrypt_request *nkreq = skcipher_request_ctx(skreq);
kfree(nkreq->dst);
}
static void nitrox_skcipher_callback(void *arg, int err)
{
struct skcipher_request *skreq = arg;
free_src_sglist(skreq);
free_dst_sglist(skreq);
if (err) {
pr_err_ratelimited("request failed status 0x%0x\n", err);
err = -EINVAL;
}
skcipher_request_complete(skreq, err);
}
static int nitrox_skcipher_crypt(struct skcipher_request *skreq, bool enc) static int nitrox_skcipher_crypt(struct skcipher_request *skreq, bool enc)
{ {
struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(skreq); struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(skreq);
...@@ -240,8 +285,28 @@ static int nitrox_skcipher_crypt(struct skcipher_request *skreq, bool enc) ...@@ -240,8 +285,28 @@ static int nitrox_skcipher_crypt(struct skcipher_request *skreq, bool enc)
} }
/* send the crypto request */ /* send the crypto request */
return nitrox_process_se_request(nctx->ndev, creq, return nitrox_process_se_request(nctx->ndev, creq, nctx->callback,
nitrox_skcipher_callback, skreq); skreq);
}
static int nitrox_cbc_decrypt(struct skcipher_request *skreq)
{
struct nitrox_kcrypt_request *nkreq = skcipher_request_ctx(skreq);
struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(skreq);
int ivsize = crypto_skcipher_ivsize(cipher);
gfp_t flags = (skreq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
GFP_KERNEL : GFP_ATOMIC;
unsigned int start = skreq->cryptlen - ivsize;
if (skreq->src != skreq->dst)
return nitrox_skcipher_crypt(skreq, false);
nkreq->iv_out = kmalloc(ivsize, flags);
if (!nkreq->iv_out)
return -ENOMEM;
scatterwalk_map_and_copy(nkreq->iv_out, skreq->src, start, ivsize, 0);
return nitrox_skcipher_crypt(skreq, false);
} }
static int nitrox_aes_encrypt(struct skcipher_request *skreq) static int nitrox_aes_encrypt(struct skcipher_request *skreq)
...@@ -340,8 +405,8 @@ static struct skcipher_alg nitrox_skciphers[] = { { ...@@ -340,8 +405,8 @@ static struct skcipher_alg nitrox_skciphers[] = { {
.ivsize = AES_BLOCK_SIZE, .ivsize = AES_BLOCK_SIZE,
.setkey = nitrox_aes_setkey, .setkey = nitrox_aes_setkey,
.encrypt = nitrox_aes_encrypt, .encrypt = nitrox_aes_encrypt,
.decrypt = nitrox_aes_decrypt, .decrypt = nitrox_cbc_decrypt,
.init = nitrox_skcipher_init, .init = nitrox_cbc_init,
.exit = nitrox_skcipher_exit, .exit = nitrox_skcipher_exit,
}, { }, {
.base = { .base = {
...@@ -455,8 +520,8 @@ static struct skcipher_alg nitrox_skciphers[] = { { ...@@ -455,8 +520,8 @@ static struct skcipher_alg nitrox_skciphers[] = { {
.ivsize = DES3_EDE_BLOCK_SIZE, .ivsize = DES3_EDE_BLOCK_SIZE,
.setkey = nitrox_3des_setkey, .setkey = nitrox_3des_setkey,
.encrypt = nitrox_3des_encrypt, .encrypt = nitrox_3des_encrypt,
.decrypt = nitrox_3des_decrypt, .decrypt = nitrox_cbc_decrypt,
.init = nitrox_skcipher_init, .init = nitrox_cbc_init,
.exit = nitrox_skcipher_exit, .exit = nitrox_skcipher_exit,
}, { }, {
.base = { .base = {
......
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