X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fcrypto%2Fnitrox%2Fnitrox_sym_reqmgr.c;h=9edb0cc00fab3fe39bd0f4e83a9fa08de0cb574e;hb=90a2ec4ae81f2ef52f7c14bfc9307e75a4127fa4;hp=4492247801f5ad8ee163759074b20728d7f55b53;hpb=ce627d633b04b45d7f0d97f2c6eefc059b6cf89e;p=dpdk.git diff --git a/drivers/crypto/nitrox/nitrox_sym_reqmgr.c b/drivers/crypto/nitrox/nitrox_sym_reqmgr.c index 4492247801..9edb0cc00f 100644 --- a/drivers/crypto/nitrox/nitrox_sym_reqmgr.c +++ b/drivers/crypto/nitrox/nitrox_sym_reqmgr.c @@ -3,7 +3,7 @@ */ #include -#include +#include #include #include @@ -238,44 +238,13 @@ create_se_instr(struct nitrox_softreq *sr, uint8_t qno) } static void -softreq_copy_iv(struct nitrox_softreq *sr) +softreq_copy_iv(struct nitrox_softreq *sr, uint8_t salt_size) { - sr->iv.virt = rte_crypto_op_ctod_offset(sr->op, uint8_t *, - sr->ctx->iv.offset); - sr->iv.iova = rte_crypto_op_ctophys_offset(sr->op, sr->ctx->iv.offset); - sr->iv.len = sr->ctx->iv.length; -} - -static int -extract_cipher_auth_digest(struct nitrox_softreq *sr, - struct nitrox_sglist *digest) -{ - struct rte_crypto_op *op = sr->op; - struct rte_mbuf *mdst = op->sym->m_dst ? op->sym->m_dst : - op->sym->m_src; - - if (sr->ctx->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY && - unlikely(!op->sym->auth.digest.data)) - return -EINVAL; - - digest->len = sr->ctx->digest_length; - if (op->sym->auth.digest.data) { - digest->iova = op->sym->auth.digest.phys_addr; - digest->virt = op->sym->auth.digest.data; - return 0; - } - - if (unlikely(rte_pktmbuf_data_len(mdst) < op->sym->auth.data.offset + - op->sym->auth.data.length + digest->len)) - return -EINVAL; + uint16_t offset = sr->ctx->iv.offset + salt_size; - digest->iova = rte_pktmbuf_iova_offset(mdst, - op->sym->auth.data.offset + - op->sym->auth.data.length); - digest->virt = rte_pktmbuf_mtod_offset(mdst, uint8_t *, - op->sym->auth.data.offset + - op->sym->auth.data.length); - return 0; + sr->iv.virt = rte_crypto_op_ctod_offset(sr->op, uint8_t *, offset); + sr->iv.iova = rte_crypto_op_ctophys_offset(sr->op, offset); + sr->iv.len = sr->ctx->iv.length - salt_size; } static void @@ -339,6 +308,143 @@ create_sglist_from_mbuf(struct nitrox_sgtable *sgtbl, struct rte_mbuf *mbuf, return 0; } +static void +create_sgcomp(struct nitrox_sgtable *sgtbl) +{ + int i, j, nr_sgcomp; + struct nitrox_sgcomp *sgcomp = sgtbl->sgcomp; + struct nitrox_sglist *sglist = sgtbl->sglist; + + nr_sgcomp = RTE_ALIGN_MUL_CEIL(sgtbl->map_bufs_cnt, 4) / 4; + sgtbl->nr_sgcomp = nr_sgcomp; + for (i = 0; i < nr_sgcomp; i++, sgcomp++) { + for (j = 0; j < 4; j++, sglist++) { + sgcomp->len[j] = rte_cpu_to_be_16(sglist->len); + sgcomp->iova[j] = rte_cpu_to_be_64(sglist->iova); + } + } +} + +static int +create_cipher_inbuf(struct nitrox_softreq *sr) +{ + int err; + struct rte_crypto_op *op = sr->op; + + fill_sglist(&sr->in, sr->iv.len, sr->iv.iova, sr->iv.virt); + err = create_sglist_from_mbuf(&sr->in, op->sym->m_src, + op->sym->cipher.data.offset, + op->sym->cipher.data.length); + if (unlikely(err)) + return err; + + create_sgcomp(&sr->in); + sr->dptr = sr->iova + offsetof(struct nitrox_softreq, in.sgcomp); + + return 0; +} + +static int +create_cipher_outbuf(struct nitrox_softreq *sr) +{ + struct rte_crypto_op *op = sr->op; + int err, cnt = 0; + struct rte_mbuf *m_dst = op->sym->m_dst ? op->sym->m_dst : + op->sym->m_src; + + sr->resp.orh = PENDING_SIG; + sr->out.sglist[cnt].len = sizeof(sr->resp.orh); + sr->out.sglist[cnt].iova = sr->iova + offsetof(struct nitrox_softreq, + resp.orh); + sr->out.sglist[cnt].virt = &sr->resp.orh; + cnt++; + + sr->out.map_bufs_cnt = cnt; + fill_sglist(&sr->out, sr->iv.len, sr->iv.iova, sr->iv.virt); + err = create_sglist_from_mbuf(&sr->out, m_dst, + op->sym->cipher.data.offset, + op->sym->cipher.data.length); + if (unlikely(err)) + return err; + + cnt = sr->out.map_bufs_cnt; + sr->resp.completion = PENDING_SIG; + sr->out.sglist[cnt].len = sizeof(sr->resp.completion); + sr->out.sglist[cnt].iova = sr->iova + offsetof(struct nitrox_softreq, + resp.completion); + sr->out.sglist[cnt].virt = &sr->resp.completion; + cnt++; + + RTE_VERIFY(cnt <= MAX_SGBUF_CNT); + sr->out.map_bufs_cnt = cnt; + + create_sgcomp(&sr->out); + sr->rptr = sr->iova + offsetof(struct nitrox_softreq, out.sgcomp); + + return 0; +} + +static void +create_cipher_gph(uint32_t cryptlen, uint16_t ivlen, struct gphdr *gph) +{ + gph->param0 = rte_cpu_to_be_16(cryptlen); + gph->param1 = 0; + gph->param2 = rte_cpu_to_be_16(ivlen); + gph->param3 = 0; +} + +static int +process_cipher_data(struct nitrox_softreq *sr) +{ + struct rte_crypto_op *op = sr->op; + int err; + + softreq_copy_iv(sr, 0); + err = create_cipher_inbuf(sr); + if (unlikely(err)) + return err; + + err = create_cipher_outbuf(sr); + if (unlikely(err)) + return err; + + create_cipher_gph(op->sym->cipher.data.length, sr->iv.len, &sr->gph); + + return 0; +} + +static int +extract_cipher_auth_digest(struct nitrox_softreq *sr, + struct nitrox_sglist *digest) +{ + struct rte_crypto_op *op = sr->op; + struct rte_mbuf *mdst = op->sym->m_dst ? op->sym->m_dst : + op->sym->m_src; + + if (sr->ctx->req_op == NITROX_OP_DECRYPT && + unlikely(!op->sym->auth.digest.data)) + return -EINVAL; + + digest->len = sr->ctx->digest_length; + if (op->sym->auth.digest.data) { + digest->iova = op->sym->auth.digest.phys_addr; + digest->virt = op->sym->auth.digest.data; + return 0; + } + + if (unlikely(rte_pktmbuf_data_len(mdst) < op->sym->auth.data.offset + + op->sym->auth.data.length + digest->len)) + return -EINVAL; + + digest->iova = rte_pktmbuf_iova_offset(mdst, + op->sym->auth.data.offset + + op->sym->auth.data.length); + digest->virt = rte_pktmbuf_mtod_offset(mdst, uint8_t *, + op->sym->auth.data.offset + + op->sym->auth.data.length); + return 0; +} + static int create_cipher_auth_sglist(struct nitrox_softreq *sr, struct nitrox_sgtable *sgtbl, struct rte_mbuf *mbuf) @@ -352,6 +458,13 @@ create_cipher_auth_sglist(struct nitrox_softreq *sr, if (unlikely(auth_only_len < 0)) return -EINVAL; + if (unlikely( + op->sym->cipher.data.offset + op->sym->cipher.data.length != + op->sym->auth.data.offset + op->sym->auth.data.length)) { + NITROX_LOG(ERR, "Auth only data after cipher data not supported\n"); + return -ENOTSUP; + } + err = create_sglist_from_mbuf(sgtbl, mbuf, op->sym->auth.data.offset, auth_only_len); if (unlikely(err)) @@ -365,35 +478,52 @@ create_cipher_auth_sglist(struct nitrox_softreq *sr, return 0; } -static void -create_sgcomp(struct nitrox_sgtable *sgtbl) +static int +create_combined_sglist(struct nitrox_softreq *sr, struct nitrox_sgtable *sgtbl, + struct rte_mbuf *mbuf) { - int i, j, nr_sgcomp; - struct nitrox_sgcomp *sgcomp = sgtbl->sgcomp; - struct nitrox_sglist *sglist = sgtbl->sglist; + struct rte_crypto_op *op = sr->op; - nr_sgcomp = RTE_ALIGN_MUL_CEIL(sgtbl->map_bufs_cnt, 4) / 4; - sgtbl->nr_sgcomp = nr_sgcomp; - for (i = 0; i < nr_sgcomp; i++, sgcomp++) { - for (j = 0; j < 4; j++, sglist++) { - sgcomp->len[j] = rte_cpu_to_be_16(sglist->len); - sgcomp->iova[j] = rte_cpu_to_be_64(sglist->iova); - } + fill_sglist(sgtbl, sr->iv.len, sr->iv.iova, sr->iv.virt); + fill_sglist(sgtbl, sr->ctx->aad_length, op->sym->aead.aad.phys_addr, + op->sym->aead.aad.data); + return create_sglist_from_mbuf(sgtbl, mbuf, op->sym->cipher.data.offset, + op->sym->cipher.data.length); +} + +static int +create_aead_sglist(struct nitrox_softreq *sr, struct nitrox_sgtable *sgtbl, + struct rte_mbuf *mbuf) +{ + int err; + + switch (sr->ctx->nitrox_chain) { + case NITROX_CHAIN_CIPHER_AUTH: + case NITROX_CHAIN_AUTH_CIPHER: + err = create_cipher_auth_sglist(sr, sgtbl, mbuf); + break; + case NITROX_CHAIN_COMBINED: + err = create_combined_sglist(sr, sgtbl, mbuf); + break; + default: + err = -EINVAL; + break; } + + return err; } static int -create_cipher_auth_inbuf(struct nitrox_softreq *sr, - struct nitrox_sglist *digest) +create_aead_inbuf(struct nitrox_softreq *sr, struct nitrox_sglist *digest) { int err; struct nitrox_crypto_ctx *ctx = sr->ctx; - err = create_cipher_auth_sglist(sr, &sr->in, sr->op->sym->m_src); + err = create_aead_sglist(sr, &sr->in, sr->op->sym->m_src); if (unlikely(err)) return err; - if (ctx->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY) + if (ctx->req_op == NITROX_OP_DECRYPT) fill_sglist(&sr->in, digest->len, digest->iova, digest->virt); create_sgcomp(&sr->in); @@ -402,25 +532,24 @@ create_cipher_auth_inbuf(struct nitrox_softreq *sr, } static int -create_cipher_auth_oop_outbuf(struct nitrox_softreq *sr, - struct nitrox_sglist *digest) +create_aead_oop_outbuf(struct nitrox_softreq *sr, struct nitrox_sglist *digest) { int err; struct nitrox_crypto_ctx *ctx = sr->ctx; - err = create_cipher_auth_sglist(sr, &sr->out, sr->op->sym->m_dst); + err = create_aead_sglist(sr, &sr->out, sr->op->sym->m_dst); if (unlikely(err)) return err; - if (ctx->auth_op == RTE_CRYPTO_AUTH_OP_GENERATE) + if (ctx->req_op == NITROX_OP_ENCRYPT) fill_sglist(&sr->out, digest->len, digest->iova, digest->virt); return 0; } static void -create_cipher_auth_inplace_outbuf(struct nitrox_softreq *sr, - struct nitrox_sglist *digest) +create_aead_inplace_outbuf(struct nitrox_softreq *sr, + struct nitrox_sglist *digest) { int i, cnt; struct nitrox_crypto_ctx *ctx = sr->ctx; @@ -433,17 +562,16 @@ create_cipher_auth_inplace_outbuf(struct nitrox_softreq *sr, } sr->out.map_bufs_cnt = cnt; - if (ctx->auth_op == RTE_CRYPTO_AUTH_OP_GENERATE) { + if (ctx->req_op == NITROX_OP_ENCRYPT) { fill_sglist(&sr->out, digest->len, digest->iova, digest->virt); - } else if (ctx->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY) { + } else if (ctx->req_op == NITROX_OP_DECRYPT) { sr->out.map_bufs_cnt--; } } static int -create_cipher_auth_outbuf(struct nitrox_softreq *sr, - struct nitrox_sglist *digest) +create_aead_outbuf(struct nitrox_softreq *sr, struct nitrox_sglist *digest) { struct rte_crypto_op *op = sr->op; int cnt = 0; @@ -458,11 +586,11 @@ create_cipher_auth_outbuf(struct nitrox_softreq *sr, if (op->sym->m_dst) { int err; - err = create_cipher_auth_oop_outbuf(sr, digest); + err = create_aead_oop_outbuf(sr, digest); if (unlikely(err)) return err; } else { - create_cipher_auth_inplace_outbuf(sr, digest); + create_aead_inplace_outbuf(sr, digest); } cnt = sr->out.map_bufs_cnt; @@ -516,16 +644,16 @@ process_cipher_auth_data(struct nitrox_softreq *sr) int err; struct nitrox_sglist digest; - softreq_copy_iv(sr); + softreq_copy_iv(sr, 0); err = extract_cipher_auth_digest(sr, &digest); if (unlikely(err)) return err; - err = create_cipher_auth_inbuf(sr, &digest); + err = create_aead_inbuf(sr, &digest); if (unlikely(err)) return err; - err = create_cipher_auth_outbuf(sr, &digest); + err = create_aead_outbuf(sr, &digest); if (unlikely(err)) return err; @@ -534,6 +662,86 @@ process_cipher_auth_data(struct nitrox_softreq *sr) return 0; } +static int +softreq_copy_salt(struct nitrox_softreq *sr) +{ + struct nitrox_crypto_ctx *ctx = sr->ctx; + uint8_t *addr; + + if (unlikely(ctx->iv.length < AES_GCM_SALT_SIZE)) { + NITROX_LOG(ERR, "Invalid IV length %d\n", ctx->iv.length); + return -EINVAL; + } + + addr = rte_crypto_op_ctod_offset(sr->op, uint8_t *, ctx->iv.offset); + if (!memcmp(ctx->salt, addr, AES_GCM_SALT_SIZE)) + return 0; + + memcpy(ctx->salt, addr, AES_GCM_SALT_SIZE); + memcpy(ctx->fctx.crypto.iv, addr, AES_GCM_SALT_SIZE); + return 0; +} + +static int +extract_combined_digest(struct nitrox_softreq *sr, struct nitrox_sglist *digest) +{ + struct rte_crypto_op *op = sr->op; + struct rte_mbuf *mdst = op->sym->m_dst ? op->sym->m_dst : + op->sym->m_src; + + digest->len = sr->ctx->digest_length; + if (op->sym->aead.digest.data) { + digest->iova = op->sym->aead.digest.phys_addr; + digest->virt = op->sym->aead.digest.data; + + return 0; + } + + if (unlikely(rte_pktmbuf_data_len(mdst) < op->sym->aead.data.offset + + op->sym->aead.data.length + digest->len)) + return -EINVAL; + + digest->iova = rte_pktmbuf_iova_offset(mdst, + op->sym->aead.data.offset + + op->sym->aead.data.length); + digest->virt = rte_pktmbuf_mtod_offset(mdst, uint8_t *, + op->sym->aead.data.offset + + op->sym->aead.data.length); + + return 0; +} + +static int +process_combined_data(struct nitrox_softreq *sr) +{ + int err; + struct nitrox_sglist digest; + struct rte_crypto_op *op = sr->op; + + err = softreq_copy_salt(sr); + if (unlikely(err)) + return err; + + softreq_copy_iv(sr, AES_GCM_SALT_SIZE); + err = extract_combined_digest(sr, &digest); + if (unlikely(err)) + return err; + + err = create_aead_inbuf(sr, &digest); + if (unlikely(err)) + return err; + + err = create_aead_outbuf(sr, &digest); + if (unlikely(err)) + return err; + + create_aead_gph(op->sym->aead.data.length, sr->iv.len, + op->sym->aead.data.length + sr->ctx->aad_length, + &sr->gph); + + return 0; +} + static int process_softreq(struct nitrox_softreq *sr) { @@ -541,10 +749,16 @@ process_softreq(struct nitrox_softreq *sr) int err = 0; switch (ctx->nitrox_chain) { + case NITROX_CHAIN_CIPHER_ONLY: + err = process_cipher_data(sr); + break; case NITROX_CHAIN_CIPHER_AUTH: case NITROX_CHAIN_AUTH_CIPHER: err = process_cipher_auth_data(sr); break; + case NITROX_CHAIN_COMBINED: + err = process_combined_data(sr); + break; default: err = -EINVAL; break; @@ -558,10 +772,15 @@ nitrox_process_se_req(uint16_t qno, struct rte_crypto_op *op, struct nitrox_crypto_ctx *ctx, struct nitrox_softreq *sr) { + int err; + softreq_init(sr, sr->iova); sr->ctx = ctx; sr->op = op; - process_softreq(sr); + err = process_softreq(sr); + if (unlikely(err)) + return err; + create_se_instr(sr, qno); sr->timeout = rte_get_timer_cycles() + CMD_TIMEOUT * rte_get_timer_hz(); return 0; @@ -577,7 +796,7 @@ nitrox_check_se_req(struct nitrox_softreq *sr, struct rte_crypto_op **op) cc = *(volatile uint64_t *)(&sr->resp.completion); orh = *(volatile uint64_t *)(&sr->resp.orh); if (cc != PENDING_SIG) - err = 0; + err = orh & 0xff; else if ((orh != PENDING_SIG) && (orh & 0xff)) err = orh & 0xff; else if (rte_get_timer_cycles() >= sr->timeout)