mirror of
https://github.com/torvalds/linux
synced 2024-09-06 18:01:05 +00:00
crypto: caam/qi - add ablkcipher and authenc algorithms
Add support to submit ablkcipher and authenc algorithms via the QI backend: -ablkcipher: cbc({aes,des,des3_ede}) ctr(aes), rfc3686(ctr(aes)) xts(aes) -authenc: authenc(hmac(md5),cbc({aes,des,des3_ede})) authenc(hmac(sha*),cbc({aes,des,des3_ede})) caam/qi being a new driver, let's wait some time to settle down without interfering with existing caam/jr driver. Accordingly, for now all caam/qi algorithms (caamalg_qi module) are marked to be of lower priority than caam/jr ones (caamalg module). Signed-off-by: Vakul Garg <vakul.garg@nxp.com> Signed-off-by: Alex Porosanu <alexandru.porosanu@nxp.com> Signed-off-by: Horia Geantă <horia.geanta@nxp.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
parent
67c2315def
commit
b189817cf7
|
@ -87,6 +87,23 @@ config CRYPTO_DEV_FSL_CAAM_CRYPTO_API
|
|||
To compile this as a module, choose M here: the module
|
||||
will be called caamalg.
|
||||
|
||||
config CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI
|
||||
tristate "Queue Interface as Crypto API backend"
|
||||
depends on CRYPTO_DEV_FSL_CAAM_JR && FSL_DPAA && NET
|
||||
default y
|
||||
select CRYPTO_AUTHENC
|
||||
select CRYPTO_BLKCIPHER
|
||||
help
|
||||
Selecting this will use CAAM Queue Interface (QI) for sending
|
||||
& receiving crypto jobs to/from CAAM. This gives better performance
|
||||
than job ring interface when the number of cores are more than the
|
||||
number of job rings assigned to the kernel. The number of portals
|
||||
assigned to the kernel should also be more than the number of
|
||||
job rings.
|
||||
|
||||
To compile this as a module, choose M here: the module
|
||||
will be called caamalg_qi.
|
||||
|
||||
config CRYPTO_DEV_FSL_CAAM_AHASH_API
|
||||
tristate "Register hash algorithm implementations with Crypto API"
|
||||
depends on CRYPTO_DEV_FSL_CAAM_JR
|
||||
|
@ -136,4 +153,5 @@ config CRYPTO_DEV_FSL_CAAM_DEBUG
|
|||
information in the CAAM driver.
|
||||
|
||||
config CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC
|
||||
def_tristate CRYPTO_DEV_FSL_CAAM_CRYPTO_API
|
||||
def_tristate (CRYPTO_DEV_FSL_CAAM_CRYPTO_API || \
|
||||
CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI)
|
||||
|
|
|
@ -8,6 +8,7 @@ endif
|
|||
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam.o
|
||||
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_JR) += caam_jr.o
|
||||
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o
|
||||
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += caamalg_qi.o
|
||||
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC) += caamalg_desc.o
|
||||
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o
|
||||
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
|
||||
|
|
|
@ -266,8 +266,9 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
|
|||
|
||||
/* aead_encrypt shared descriptor */
|
||||
desc = ctx->sh_desc_enc;
|
||||
cnstr_shdsc_aead_encap(desc, &ctx->cdata, &ctx->adata, ctx->authsize,
|
||||
is_rfc3686, nonce, ctx1_iv_off);
|
||||
cnstr_shdsc_aead_encap(desc, &ctx->cdata, &ctx->adata, ivsize,
|
||||
ctx->authsize, is_rfc3686, nonce, ctx1_iv_off,
|
||||
false);
|
||||
dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma,
|
||||
desc_bytes(desc), DMA_TO_DEVICE);
|
||||
|
||||
|
@ -299,7 +300,7 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
|
|||
desc = ctx->sh_desc_dec;
|
||||
cnstr_shdsc_aead_decap(desc, &ctx->cdata, &ctx->adata, ivsize,
|
||||
ctx->authsize, alg->caam.geniv, is_rfc3686,
|
||||
nonce, ctx1_iv_off);
|
||||
nonce, ctx1_iv_off, false);
|
||||
dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma,
|
||||
desc_bytes(desc), DMA_TO_DEVICE);
|
||||
|
||||
|
@ -333,7 +334,7 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
|
|||
desc = ctx->sh_desc_enc;
|
||||
cnstr_shdsc_aead_givencap(desc, &ctx->cdata, &ctx->adata, ivsize,
|
||||
ctx->authsize, is_rfc3686, nonce,
|
||||
ctx1_iv_off);
|
||||
ctx1_iv_off, false);
|
||||
dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma,
|
||||
desc_bytes(desc), DMA_TO_DEVICE);
|
||||
|
||||
|
|
|
@ -265,17 +265,19 @@ static void init_sh_desc_key_aead(u32 * const desc,
|
|||
* split key is to be used, the size of the split key itself is
|
||||
* specified. Valid algorithm values - one of OP_ALG_ALGSEL_{MD5, SHA1,
|
||||
* SHA224, SHA256, SHA384, SHA512} ANDed with OP_ALG_AAI_HMAC_PRECOMP.
|
||||
* @ivsize: initialization vector size
|
||||
* @icvsize: integrity check value (ICV) size (truncated or full)
|
||||
* @is_rfc3686: true when ctr(aes) is wrapped by rfc3686 template
|
||||
* @nonce: pointer to rfc3686 nonce
|
||||
* @ctx1_iv_off: IV offset in CONTEXT1 register
|
||||
* @is_qi: true when called from caam/qi
|
||||
*
|
||||
* Note: Requires an MDHA split key.
|
||||
*/
|
||||
void cnstr_shdsc_aead_encap(u32 * const desc, struct alginfo *cdata,
|
||||
struct alginfo *adata, unsigned int icvsize,
|
||||
const bool is_rfc3686, u32 *nonce,
|
||||
const u32 ctx1_iv_off)
|
||||
struct alginfo *adata, unsigned int ivsize,
|
||||
unsigned int icvsize, const bool is_rfc3686,
|
||||
u32 *nonce, const u32 ctx1_iv_off, const bool is_qi)
|
||||
{
|
||||
/* Note: Context registers are saved. */
|
||||
init_sh_desc_key_aead(desc, cdata, adata, is_rfc3686, nonce);
|
||||
|
@ -284,6 +286,25 @@ void cnstr_shdsc_aead_encap(u32 * const desc, struct alginfo *cdata,
|
|||
append_operation(desc, adata->algtype | OP_ALG_AS_INITFINAL |
|
||||
OP_ALG_ENCRYPT);
|
||||
|
||||
if (is_qi) {
|
||||
u32 *wait_load_cmd;
|
||||
|
||||
/* REG3 = assoclen */
|
||||
append_seq_load(desc, 4, LDST_CLASS_DECO |
|
||||
LDST_SRCDST_WORD_DECO_MATH3 |
|
||||
(4 << LDST_OFFSET_SHIFT));
|
||||
|
||||
wait_load_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
|
||||
JUMP_COND_CALM | JUMP_COND_NCP |
|
||||
JUMP_COND_NOP | JUMP_COND_NIP |
|
||||
JUMP_COND_NIFP);
|
||||
set_jump_tgt_here(desc, wait_load_cmd);
|
||||
|
||||
append_seq_load(desc, ivsize, LDST_CLASS_1_CCB |
|
||||
LDST_SRCDST_BYTE_CONTEXT |
|
||||
(ctx1_iv_off << LDST_OFFSET_SHIFT));
|
||||
}
|
||||
|
||||
/* Read and write assoclen bytes */
|
||||
append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
|
||||
append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
|
||||
|
@ -338,6 +359,7 @@ EXPORT_SYMBOL(cnstr_shdsc_aead_encap);
|
|||
* @is_rfc3686: true when ctr(aes) is wrapped by rfc3686 template
|
||||
* @nonce: pointer to rfc3686 nonce
|
||||
* @ctx1_iv_off: IV offset in CONTEXT1 register
|
||||
* @is_qi: true when called from caam/qi
|
||||
*
|
||||
* Note: Requires an MDHA split key.
|
||||
*/
|
||||
|
@ -345,7 +367,7 @@ void cnstr_shdsc_aead_decap(u32 * const desc, struct alginfo *cdata,
|
|||
struct alginfo *adata, unsigned int ivsize,
|
||||
unsigned int icvsize, const bool geniv,
|
||||
const bool is_rfc3686, u32 *nonce,
|
||||
const u32 ctx1_iv_off)
|
||||
const u32 ctx1_iv_off, const bool is_qi)
|
||||
{
|
||||
/* Note: Context registers are saved. */
|
||||
init_sh_desc_key_aead(desc, cdata, adata, is_rfc3686, nonce);
|
||||
|
@ -354,6 +376,26 @@ void cnstr_shdsc_aead_decap(u32 * const desc, struct alginfo *cdata,
|
|||
append_operation(desc, adata->algtype | OP_ALG_AS_INITFINAL |
|
||||
OP_ALG_DECRYPT | OP_ALG_ICV_ON);
|
||||
|
||||
if (is_qi) {
|
||||
u32 *wait_load_cmd;
|
||||
|
||||
/* REG3 = assoclen */
|
||||
append_seq_load(desc, 4, LDST_CLASS_DECO |
|
||||
LDST_SRCDST_WORD_DECO_MATH3 |
|
||||
(4 << LDST_OFFSET_SHIFT));
|
||||
|
||||
wait_load_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
|
||||
JUMP_COND_CALM | JUMP_COND_NCP |
|
||||
JUMP_COND_NOP | JUMP_COND_NIP |
|
||||
JUMP_COND_NIFP);
|
||||
set_jump_tgt_here(desc, wait_load_cmd);
|
||||
|
||||
if (!geniv)
|
||||
append_seq_load(desc, ivsize, LDST_CLASS_1_CCB |
|
||||
LDST_SRCDST_BYTE_CONTEXT |
|
||||
(ctx1_iv_off << LDST_OFFSET_SHIFT));
|
||||
}
|
||||
|
||||
/* Read and write assoclen bytes */
|
||||
append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
|
||||
if (geniv)
|
||||
|
@ -423,21 +465,44 @@ EXPORT_SYMBOL(cnstr_shdsc_aead_decap);
|
|||
* @is_rfc3686: true when ctr(aes) is wrapped by rfc3686 template
|
||||
* @nonce: pointer to rfc3686 nonce
|
||||
* @ctx1_iv_off: IV offset in CONTEXT1 register
|
||||
* @is_qi: true when called from caam/qi
|
||||
*
|
||||
* Note: Requires an MDHA split key.
|
||||
*/
|
||||
void cnstr_shdsc_aead_givencap(u32 * const desc, struct alginfo *cdata,
|
||||
struct alginfo *adata, unsigned int ivsize,
|
||||
unsigned int icvsize, const bool is_rfc3686,
|
||||
u32 *nonce, const u32 ctx1_iv_off)
|
||||
u32 *nonce, const u32 ctx1_iv_off,
|
||||
const bool is_qi)
|
||||
{
|
||||
u32 geniv, moveiv;
|
||||
|
||||
/* Note: Context registers are saved. */
|
||||
init_sh_desc_key_aead(desc, cdata, adata, is_rfc3686, nonce);
|
||||
|
||||
if (is_rfc3686)
|
||||
if (is_qi) {
|
||||
u32 *wait_load_cmd;
|
||||
|
||||
/* REG3 = assoclen */
|
||||
append_seq_load(desc, 4, LDST_CLASS_DECO |
|
||||
LDST_SRCDST_WORD_DECO_MATH3 |
|
||||
(4 << LDST_OFFSET_SHIFT));
|
||||
|
||||
wait_load_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
|
||||
JUMP_COND_CALM | JUMP_COND_NCP |
|
||||
JUMP_COND_NOP | JUMP_COND_NIP |
|
||||
JUMP_COND_NIFP);
|
||||
set_jump_tgt_here(desc, wait_load_cmd);
|
||||
}
|
||||
|
||||
if (is_rfc3686) {
|
||||
if (is_qi)
|
||||
append_seq_load(desc, ivsize, LDST_CLASS_1_CCB |
|
||||
LDST_SRCDST_BYTE_CONTEXT |
|
||||
(ctx1_iv_off << LDST_OFFSET_SHIFT));
|
||||
|
||||
goto copy_iv;
|
||||
}
|
||||
|
||||
/* Generate IV */
|
||||
geniv = NFIFOENTRY_STYPE_PAD | NFIFOENTRY_DEST_DECO |
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
#define DESC_AEAD_ENC_LEN (DESC_AEAD_BASE + 11 * CAAM_CMD_SZ)
|
||||
#define DESC_AEAD_DEC_LEN (DESC_AEAD_BASE + 15 * CAAM_CMD_SZ)
|
||||
#define DESC_AEAD_GIVENC_LEN (DESC_AEAD_ENC_LEN + 7 * CAAM_CMD_SZ)
|
||||
#define DESC_QI_AEAD_ENC_LEN (DESC_AEAD_ENC_LEN + 3 * CAAM_CMD_SZ)
|
||||
#define DESC_QI_AEAD_DEC_LEN (DESC_AEAD_DEC_LEN + 3 * CAAM_CMD_SZ)
|
||||
#define DESC_QI_AEAD_GIVENC_LEN (DESC_AEAD_GIVENC_LEN + 3 * CAAM_CMD_SZ)
|
||||
|
||||
/* Note: Nonce is counted in cdata.keylen */
|
||||
#define DESC_AEAD_CTR_RFC3686_LEN (4 * CAAM_CMD_SZ)
|
||||
|
@ -45,20 +48,22 @@ void cnstr_shdsc_aead_null_decap(u32 * const desc, struct alginfo *adata,
|
|||
unsigned int icvsize);
|
||||
|
||||
void cnstr_shdsc_aead_encap(u32 * const desc, struct alginfo *cdata,
|
||||
struct alginfo *adata, unsigned int icvsize,
|
||||
const bool is_rfc3686, u32 *nonce,
|
||||
const u32 ctx1_iv_off);
|
||||
struct alginfo *adata, unsigned int ivsize,
|
||||
unsigned int icvsize, const bool is_rfc3686,
|
||||
u32 *nonce, const u32 ctx1_iv_off,
|
||||
const bool is_qi);
|
||||
|
||||
void cnstr_shdsc_aead_decap(u32 * const desc, struct alginfo *cdata,
|
||||
struct alginfo *adata, unsigned int ivsize,
|
||||
unsigned int icvsize, const bool geniv,
|
||||
const bool is_rfc3686, u32 *nonce,
|
||||
const u32 ctx1_iv_off);
|
||||
const u32 ctx1_iv_off, const bool is_qi);
|
||||
|
||||
void cnstr_shdsc_aead_givencap(u32 * const desc, struct alginfo *cdata,
|
||||
struct alginfo *adata, unsigned int ivsize,
|
||||
unsigned int icvsize, const bool is_rfc3686,
|
||||
u32 *nonce, const u32 ctx1_iv_off);
|
||||
u32 *nonce, const u32 ctx1_iv_off,
|
||||
const bool is_qi);
|
||||
|
||||
void cnstr_shdsc_gcm_encap(u32 * const desc, struct alginfo *cdata,
|
||||
unsigned int icvsize);
|
||||
|
|
2387
drivers/crypto/caam/caamalg_qi.c
Normal file
2387
drivers/crypto/caam/caamalg_qi.c
Normal file
File diff suppressed because it is too large
Load diff
108
drivers/crypto/caam/sg_sw_qm.h
Normal file
108
drivers/crypto/caam/sg_sw_qm.h
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright 2013-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Freescale Semiconductor nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") as published by the Free Software
|
||||
* Foundation, either version 2 of that License or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __SG_SW_QM_H
|
||||
#define __SG_SW_QM_H
|
||||
|
||||
#include <soc/fsl/qman.h>
|
||||
#include "regs.h"
|
||||
|
||||
static inline void __dma_to_qm_sg(struct qm_sg_entry *qm_sg_ptr, dma_addr_t dma,
|
||||
u16 offset)
|
||||
{
|
||||
qm_sg_entry_set64(qm_sg_ptr, dma);
|
||||
qm_sg_ptr->__reserved2 = 0;
|
||||
qm_sg_ptr->bpid = 0;
|
||||
qm_sg_ptr->offset = cpu_to_be16(offset & QM_SG_OFF_MASK);
|
||||
}
|
||||
|
||||
static inline void dma_to_qm_sg_one(struct qm_sg_entry *qm_sg_ptr,
|
||||
dma_addr_t dma, u32 len, u16 offset)
|
||||
{
|
||||
__dma_to_qm_sg(qm_sg_ptr, dma, offset);
|
||||
qm_sg_entry_set_len(qm_sg_ptr, len);
|
||||
}
|
||||
|
||||
static inline void dma_to_qm_sg_one_last(struct qm_sg_entry *qm_sg_ptr,
|
||||
dma_addr_t dma, u32 len, u16 offset)
|
||||
{
|
||||
__dma_to_qm_sg(qm_sg_ptr, dma, offset);
|
||||
qm_sg_entry_set_f(qm_sg_ptr, len);
|
||||
}
|
||||
|
||||
static inline void dma_to_qm_sg_one_ext(struct qm_sg_entry *qm_sg_ptr,
|
||||
dma_addr_t dma, u32 len, u16 offset)
|
||||
{
|
||||
__dma_to_qm_sg(qm_sg_ptr, dma, offset);
|
||||
qm_sg_ptr->cfg = cpu_to_be32(QM_SG_EXT | (len & QM_SG_LEN_MASK));
|
||||
}
|
||||
|
||||
static inline void dma_to_qm_sg_one_last_ext(struct qm_sg_entry *qm_sg_ptr,
|
||||
dma_addr_t dma, u32 len,
|
||||
u16 offset)
|
||||
{
|
||||
__dma_to_qm_sg(qm_sg_ptr, dma, offset);
|
||||
qm_sg_ptr->cfg = cpu_to_be32(QM_SG_EXT | QM_SG_FIN |
|
||||
(len & QM_SG_LEN_MASK));
|
||||
}
|
||||
|
||||
/*
|
||||
* convert scatterlist to h/w link table format
|
||||
* but does not have final bit; instead, returns last entry
|
||||
*/
|
||||
static inline struct qm_sg_entry *
|
||||
sg_to_qm_sg(struct scatterlist *sg, int sg_count,
|
||||
struct qm_sg_entry *qm_sg_ptr, u16 offset)
|
||||
{
|
||||
while (sg_count && sg) {
|
||||
dma_to_qm_sg_one(qm_sg_ptr, sg_dma_address(sg),
|
||||
sg_dma_len(sg), offset);
|
||||
qm_sg_ptr++;
|
||||
sg = sg_next(sg);
|
||||
sg_count--;
|
||||
}
|
||||
return qm_sg_ptr - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* convert scatterlist to h/w link table format
|
||||
* scatterlist must have been previously dma mapped
|
||||
*/
|
||||
static inline void sg_to_qm_sg_last(struct scatterlist *sg, int sg_count,
|
||||
struct qm_sg_entry *qm_sg_ptr, u16 offset)
|
||||
{
|
||||
qm_sg_ptr = sg_to_qm_sg(sg, sg_count, qm_sg_ptr, offset);
|
||||
qm_sg_entry_set_f(qm_sg_ptr, qm_sg_entry_get_len(qm_sg_ptr));
|
||||
}
|
||||
|
||||
#endif /* __SG_SW_QM_H */
|
Loading…
Reference in a new issue