Commit 879f77e9 authored by Salvatore Benedetto's avatar Salvatore Benedetto Committed by Herbert Xu

crypto: qat - Add RSA CRT mode

Extend qat driver to use RSA CRT mode when all CRT related components are
present in the private key. Simplify code in qat_rsa_setkey by adding
qat_rsa_clear_ctx.
Signed-off-by: default avatarSalvatore Benedetto <salvatore.benedetto@intel.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent c8afbc84
...@@ -73,6 +73,14 @@ struct qat_rsa_input_params { ...@@ -73,6 +73,14 @@ struct qat_rsa_input_params {
dma_addr_t d; dma_addr_t d;
dma_addr_t n; dma_addr_t n;
} dec; } dec;
struct {
dma_addr_t c;
dma_addr_t p;
dma_addr_t q;
dma_addr_t dp;
dma_addr_t dq;
dma_addr_t qinv;
} dec_crt;
u64 in_tab[8]; u64 in_tab[8];
}; };
} __packed __aligned(64); } __packed __aligned(64);
...@@ -93,10 +101,21 @@ struct qat_rsa_ctx { ...@@ -93,10 +101,21 @@ struct qat_rsa_ctx {
char *n; char *n;
char *e; char *e;
char *d; char *d;
char *p;
char *q;
char *dp;
char *dq;
char *qinv;
dma_addr_t dma_n; dma_addr_t dma_n;
dma_addr_t dma_e; dma_addr_t dma_e;
dma_addr_t dma_d; dma_addr_t dma_d;
dma_addr_t dma_p;
dma_addr_t dma_q;
dma_addr_t dma_dp;
dma_addr_t dma_dq;
dma_addr_t dma_qinv;
unsigned int key_sz; unsigned int key_sz;
bool crt_mode;
struct qat_crypto_instance *inst; struct qat_crypto_instance *inst;
} __packed __aligned(64); } __packed __aligned(64);
...@@ -235,6 +254,35 @@ static unsigned long qat_rsa_dec_fn_id(unsigned int len) ...@@ -235,6 +254,35 @@ static unsigned long qat_rsa_dec_fn_id(unsigned int len)
}; };
} }
#define PKE_RSA_DP2_512 0x1c131b57
#define PKE_RSA_DP2_1024 0x26131c2d
#define PKE_RSA_DP2_1536 0x45111d12
#define PKE_RSA_DP2_2048 0x59121dfa
#define PKE_RSA_DP2_3072 0x81121ed9
#define PKE_RSA_DP2_4096 0xb1111fb2
static unsigned long qat_rsa_dec_fn_id_crt(unsigned int len)
{
unsigned int bitslen = len << 3;
switch (bitslen) {
case 512:
return PKE_RSA_DP2_512;
case 1024:
return PKE_RSA_DP2_1024;
case 1536:
return PKE_RSA_DP2_1536;
case 2048:
return PKE_RSA_DP2_2048;
case 3072:
return PKE_RSA_DP2_3072;
case 4096:
return PKE_RSA_DP2_4096;
default:
return 0;
};
}
static int qat_rsa_enc(struct akcipher_request *req) static int qat_rsa_enc(struct akcipher_request *req)
{ {
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
...@@ -388,7 +436,9 @@ static int qat_rsa_dec(struct akcipher_request *req) ...@@ -388,7 +436,9 @@ static int qat_rsa_dec(struct akcipher_request *req)
memset(msg, '\0', sizeof(*msg)); memset(msg, '\0', sizeof(*msg));
ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(msg->pke_hdr, ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(msg->pke_hdr,
ICP_QAT_FW_COMN_REQ_FLAG_SET); ICP_QAT_FW_COMN_REQ_FLAG_SET);
msg->pke_hdr.cd_pars.func_id = qat_rsa_dec_fn_id(ctx->key_sz); msg->pke_hdr.cd_pars.func_id = ctx->crt_mode ?
qat_rsa_dec_fn_id_crt(ctx->key_sz) :
qat_rsa_dec_fn_id(ctx->key_sz);
if (unlikely(!msg->pke_hdr.cd_pars.func_id)) if (unlikely(!msg->pke_hdr.cd_pars.func_id))
return -EINVAL; return -EINVAL;
...@@ -398,8 +448,16 @@ static int qat_rsa_dec(struct akcipher_request *req) ...@@ -398,8 +448,16 @@ static int qat_rsa_dec(struct akcipher_request *req)
ICP_QAT_FW_COMN_FLAGS_BUILD(QAT_COMN_PTR_TYPE_FLAT, ICP_QAT_FW_COMN_FLAGS_BUILD(QAT_COMN_PTR_TYPE_FLAT,
QAT_COMN_CD_FLD_TYPE_64BIT_ADR); QAT_COMN_CD_FLD_TYPE_64BIT_ADR);
if (ctx->crt_mode) {
qat_req->in.dec_crt.p = ctx->dma_p;
qat_req->in.dec_crt.q = ctx->dma_q;
qat_req->in.dec_crt.dp = ctx->dma_dp;
qat_req->in.dec_crt.dq = ctx->dma_dq;
qat_req->in.dec_crt.qinv = ctx->dma_qinv;
} else {
qat_req->in.dec.d = ctx->dma_d; qat_req->in.dec.d = ctx->dma_d;
qat_req->in.dec.n = ctx->dma_n; qat_req->in.dec.n = ctx->dma_n;
}
ret = -ENOMEM; ret = -ENOMEM;
/* /*
...@@ -446,6 +504,9 @@ static int qat_rsa_dec(struct akcipher_request *req) ...@@ -446,6 +504,9 @@ static int qat_rsa_dec(struct akcipher_request *req)
} }
if (ctx->crt_mode)
qat_req->in.in_tab[6] = 0;
else
qat_req->in.in_tab[3] = 0; qat_req->in.in_tab[3] = 0;
qat_req->out.out_tab[1] = 0; qat_req->out.out_tab[1] = 0;
qat_req->phy_in = dma_map_single(dev, &qat_req->in.dec.c, qat_req->phy_in = dma_map_single(dev, &qat_req->in.dec.c,
...@@ -463,7 +524,11 @@ static int qat_rsa_dec(struct akcipher_request *req) ...@@ -463,7 +524,11 @@ static int qat_rsa_dec(struct akcipher_request *req)
msg->pke_mid.src_data_addr = qat_req->phy_in; msg->pke_mid.src_data_addr = qat_req->phy_in;
msg->pke_mid.dest_data_addr = qat_req->phy_out; msg->pke_mid.dest_data_addr = qat_req->phy_out;
msg->pke_mid.opaque = (uint64_t)(__force long)req; msg->pke_mid.opaque = (uint64_t)(__force long)req;
if (ctx->crt_mode)
msg->input_param_count = 6;
else
msg->input_param_count = 3; msg->input_param_count = 3;
msg->output_param_count = 1; msg->output_param_count = 1;
do { do {
ret = adf_send_message(ctx->inst->pke_tx, (uint32_t *)msg); ret = adf_send_message(ctx->inst->pke_tx, (uint32_t *)msg);
...@@ -583,13 +648,106 @@ int qat_rsa_set_d(struct qat_rsa_ctx *ctx, const char *value, size_t vlen) ...@@ -583,13 +648,106 @@ int qat_rsa_set_d(struct qat_rsa_ctx *ctx, const char *value, size_t vlen)
return ret; return ret;
} }
static int qat_rsa_setkey(struct crypto_akcipher *tfm, const void *key, static void qat_rsa_drop_leading_zeros(const char **ptr, unsigned int *len)
unsigned int keylen, bool private)
{ {
struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm); while (!**ptr && *len) {
struct device *dev = &GET_DEV(ctx->inst->accel_dev); (*ptr)++;
struct rsa_key rsa_key; (*len)--;
int ret; }
}
static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
{
struct qat_crypto_instance *inst = ctx->inst;
struct device *dev = &GET_DEV(inst->accel_dev);
const char *ptr;
unsigned int len;
unsigned int half_key_sz = ctx->key_sz / 2;
/* p */
ptr = rsa_key->p;
len = rsa_key->p_sz;
qat_rsa_drop_leading_zeros(&ptr, &len);
if (!len)
goto err;
ctx->p = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_p, GFP_KERNEL);
if (!ctx->p)
goto err;
memcpy(ctx->p + (half_key_sz - len), ptr, len);
/* q */
ptr = rsa_key->q;
len = rsa_key->q_sz;
qat_rsa_drop_leading_zeros(&ptr, &len);
if (!len)
goto free_p;
ctx->q = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_q, GFP_KERNEL);
if (!ctx->q)
goto free_p;
memcpy(ctx->q + (half_key_sz - len), ptr, len);
/* dp */
ptr = rsa_key->dp;
len = rsa_key->dp_sz;
qat_rsa_drop_leading_zeros(&ptr, &len);
if (!len)
goto free_q;
ctx->dp = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_dp,
GFP_KERNEL);
if (!ctx->dp)
goto free_q;
memcpy(ctx->dp + (half_key_sz - len), ptr, len);
/* dq */
ptr = rsa_key->dq;
len = rsa_key->dq_sz;
qat_rsa_drop_leading_zeros(&ptr, &len);
if (!len)
goto free_dp;
ctx->dq = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_dq,
GFP_KERNEL);
if (!ctx->dq)
goto free_dp;
memcpy(ctx->dq + (half_key_sz - len), ptr, len);
/* qinv */
ptr = rsa_key->qinv;
len = rsa_key->qinv_sz;
qat_rsa_drop_leading_zeros(&ptr, &len);
if (!len)
goto free_dq;
ctx->qinv = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_qinv,
GFP_KERNEL);
if (!ctx->qinv)
goto free_dq;
memcpy(ctx->qinv + (half_key_sz - len), ptr, len);
ctx->crt_mode = true;
return;
free_dq:
memset(ctx->dq, '\0', half_key_sz);
dma_free_coherent(dev, half_key_sz, ctx->dq, ctx->dma_dq);
ctx->dq = NULL;
free_dp:
memset(ctx->dp, '\0', half_key_sz);
dma_free_coherent(dev, half_key_sz, ctx->dp, ctx->dma_dp);
ctx->dp = NULL;
free_q:
memset(ctx->q, '\0', half_key_sz);
dma_free_coherent(dev, half_key_sz, ctx->q, ctx->dma_q);
ctx->q = NULL;
free_p:
memset(ctx->p, '\0', half_key_sz);
dma_free_coherent(dev, half_key_sz, ctx->p, ctx->dma_p);
ctx->p = NULL;
err:
ctx->crt_mode = false;
}
static void qat_rsa_clear_ctx(struct device *dev, struct qat_rsa_ctx *ctx)
{
unsigned int half_key_sz = ctx->key_sz / 2;
/* Free the old key if any */ /* Free the old key if any */
if (ctx->n) if (ctx->n)
...@@ -600,10 +758,48 @@ static int qat_rsa_setkey(struct crypto_akcipher *tfm, const void *key, ...@@ -600,10 +758,48 @@ static int qat_rsa_setkey(struct crypto_akcipher *tfm, const void *key,
memset(ctx->d, '\0', ctx->key_sz); memset(ctx->d, '\0', ctx->key_sz);
dma_free_coherent(dev, ctx->key_sz, ctx->d, ctx->dma_d); dma_free_coherent(dev, ctx->key_sz, ctx->d, ctx->dma_d);
} }
if (ctx->p) {
memset(ctx->p, '\0', half_key_sz);
dma_free_coherent(dev, half_key_sz, ctx->p, ctx->dma_p);
}
if (ctx->q) {
memset(ctx->q, '\0', half_key_sz);
dma_free_coherent(dev, half_key_sz, ctx->q, ctx->dma_q);
}
if (ctx->dp) {
memset(ctx->dp, '\0', half_key_sz);
dma_free_coherent(dev, half_key_sz, ctx->dp, ctx->dma_dp);
}
if (ctx->dq) {
memset(ctx->dq, '\0', half_key_sz);
dma_free_coherent(dev, half_key_sz, ctx->dq, ctx->dma_dq);
}
if (ctx->qinv) {
memset(ctx->qinv, '\0', half_key_sz);
dma_free_coherent(dev, half_key_sz, ctx->qinv, ctx->dma_qinv);
}
ctx->n = NULL; ctx->n = NULL;
ctx->e = NULL; ctx->e = NULL;
ctx->d = NULL; ctx->d = NULL;
ctx->p = NULL;
ctx->q = NULL;
ctx->dp = NULL;
ctx->dq = NULL;
ctx->qinv = NULL;
ctx->crt_mode = false;
ctx->key_sz = 0;
}
static int qat_rsa_setkey(struct crypto_akcipher *tfm, const void *key,
unsigned int keylen, bool private)
{
struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
struct device *dev = &GET_DEV(ctx->inst->accel_dev);
struct rsa_key rsa_key;
int ret;
qat_rsa_clear_ctx(dev, ctx);
if (private) if (private)
ret = rsa_parse_priv_key(&rsa_key, key, keylen); ret = rsa_parse_priv_key(&rsa_key, key, keylen);
...@@ -622,6 +818,7 @@ static int qat_rsa_setkey(struct crypto_akcipher *tfm, const void *key, ...@@ -622,6 +818,7 @@ static int qat_rsa_setkey(struct crypto_akcipher *tfm, const void *key,
ret = qat_rsa_set_d(ctx, rsa_key.d, rsa_key.d_sz); ret = qat_rsa_set_d(ctx, rsa_key.d, rsa_key.d_sz);
if (ret < 0) if (ret < 0)
goto free; goto free;
qat_rsa_setkey_crt(ctx, &rsa_key);
} }
if (!ctx->n || !ctx->e) { if (!ctx->n || !ctx->e) {
...@@ -637,20 +834,7 @@ static int qat_rsa_setkey(struct crypto_akcipher *tfm, const void *key, ...@@ -637,20 +834,7 @@ static int qat_rsa_setkey(struct crypto_akcipher *tfm, const void *key,
return 0; return 0;
free: free:
if (ctx->d) { qat_rsa_clear_ctx(dev, ctx);
memset(ctx->d, '\0', ctx->key_sz);
dma_free_coherent(dev, ctx->key_sz, ctx->d, ctx->dma_d);
ctx->d = NULL;
}
if (ctx->e) {
dma_free_coherent(dev, ctx->key_sz, ctx->e, ctx->dma_e);
ctx->e = NULL;
}
if (ctx->n) {
dma_free_coherent(dev, ctx->key_sz, ctx->n, ctx->dma_n);
ctx->n = NULL;
ctx->key_sz = 0;
}
return ret; return ret;
} }
......
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