mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-18 14:07:05 +07:00
7e0880b9fb
Offload split key generation in CAAM engine, using DKP. DKP is supported starting with Era 6. Note that the way assoclen is transmitted from the job descriptor to the shared descriptor changes - DPOVRD register is used instead of MATH3 (where available), since DKP protocol thrashes the MATH registers. The replacement of MDHA split key generation with DKP has the side effect of the crypto engine writing the authentication key, and thus the DMA mapping direction for the buffer holding the key has to change from DMA_TO_DEVICE to DMA_BIDIRECTIONAL. There are two cases: -key is inlined in descriptor - descriptor buffer mapping changes -key is referenced - key buffer mapping changes Signed-off-by: Horia Geantă <horia.geanta@nxp.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1409 lines
47 KiB
C
1409 lines
47 KiB
C
/*
|
|
* Shared descriptors for aead, ablkcipher algorithms
|
|
*
|
|
* Copyright 2016 NXP
|
|
*/
|
|
|
|
#include "compat.h"
|
|
#include "desc_constr.h"
|
|
#include "caamalg_desc.h"
|
|
|
|
/*
|
|
* For aead functions, read payload and write payload,
|
|
* both of which are specified in req->src and req->dst
|
|
*/
|
|
static inline void aead_append_src_dst(u32 *desc, u32 msg_type)
|
|
{
|
|
append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF);
|
|
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH |
|
|
KEY_VLF | msg_type | FIFOLD_TYPE_LASTBOTH);
|
|
}
|
|
|
|
/* Set DK bit in class 1 operation if shared */
|
|
static inline void append_dec_op1(u32 *desc, u32 type)
|
|
{
|
|
u32 *jump_cmd, *uncond_jump_cmd;
|
|
|
|
/* DK bit is valid only for AES */
|
|
if ((type & OP_ALG_ALGSEL_MASK) != OP_ALG_ALGSEL_AES) {
|
|
append_operation(desc, type | OP_ALG_AS_INITFINAL |
|
|
OP_ALG_DECRYPT);
|
|
return;
|
|
}
|
|
|
|
jump_cmd = append_jump(desc, JUMP_TEST_ALL | JUMP_COND_SHRD);
|
|
append_operation(desc, type | OP_ALG_AS_INITFINAL |
|
|
OP_ALG_DECRYPT);
|
|
uncond_jump_cmd = append_jump(desc, JUMP_TEST_ALL);
|
|
set_jump_tgt_here(desc, jump_cmd);
|
|
append_operation(desc, type | OP_ALG_AS_INITFINAL |
|
|
OP_ALG_DECRYPT | OP_ALG_AAI_DK);
|
|
set_jump_tgt_here(desc, uncond_jump_cmd);
|
|
}
|
|
|
|
/**
|
|
* cnstr_shdsc_aead_null_encap - IPSec ESP encapsulation shared descriptor
|
|
* (non-protocol) with no (null) encryption.
|
|
* @desc: pointer to buffer used for descriptor construction
|
|
* @adata: pointer to authentication transform definitions.
|
|
* A split key is required for SEC Era < 6; the size of the split key
|
|
* is specified in this case. Valid algorithm values - one of
|
|
* OP_ALG_ALGSEL_{MD5, SHA1, SHA224, SHA256, SHA384, SHA512} ANDed
|
|
* with OP_ALG_AAI_HMAC_PRECOMP.
|
|
* @icvsize: integrity check value (ICV) size (truncated or full)
|
|
* @era: SEC Era
|
|
*/
|
|
void cnstr_shdsc_aead_null_encap(u32 * const desc, struct alginfo *adata,
|
|
unsigned int icvsize, int era)
|
|
{
|
|
u32 *key_jump_cmd, *read_move_cmd, *write_move_cmd;
|
|
|
|
init_sh_desc(desc, HDR_SHARE_SERIAL);
|
|
|
|
/* Skip if already shared */
|
|
key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
|
|
JUMP_COND_SHRD);
|
|
if (era < 6) {
|
|
if (adata->key_inline)
|
|
append_key_as_imm(desc, adata->key_virt,
|
|
adata->keylen_pad, adata->keylen,
|
|
CLASS_2 | KEY_DEST_MDHA_SPLIT |
|
|
KEY_ENC);
|
|
else
|
|
append_key(desc, adata->key_dma, adata->keylen,
|
|
CLASS_2 | KEY_DEST_MDHA_SPLIT | KEY_ENC);
|
|
} else {
|
|
append_proto_dkp(desc, adata);
|
|
}
|
|
set_jump_tgt_here(desc, key_jump_cmd);
|
|
|
|
/* assoclen + cryptlen = seqinlen */
|
|
append_math_sub(desc, REG3, SEQINLEN, REG0, CAAM_CMD_SZ);
|
|
|
|
/* Prepare to read and write cryptlen + assoclen bytes */
|
|
append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
|
|
append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
|
|
|
|
/*
|
|
* MOVE_LEN opcode is not available in all SEC HW revisions,
|
|
* thus need to do some magic, i.e. self-patch the descriptor
|
|
* buffer.
|
|
*/
|
|
read_move_cmd = append_move(desc, MOVE_SRC_DESCBUF |
|
|
MOVE_DEST_MATH3 |
|
|
(0x6 << MOVE_LEN_SHIFT));
|
|
write_move_cmd = append_move(desc, MOVE_SRC_MATH3 |
|
|
MOVE_DEST_DESCBUF |
|
|
MOVE_WAITCOMP |
|
|
(0x8 << MOVE_LEN_SHIFT));
|
|
|
|
/* Class 2 operation */
|
|
append_operation(desc, adata->algtype | OP_ALG_AS_INITFINAL |
|
|
OP_ALG_ENCRYPT);
|
|
|
|
/* Read and write cryptlen bytes */
|
|
aead_append_src_dst(desc, FIFOLD_TYPE_MSG | FIFOLD_TYPE_FLUSH1);
|
|
|
|
set_move_tgt_here(desc, read_move_cmd);
|
|
set_move_tgt_here(desc, write_move_cmd);
|
|
append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
|
|
append_move(desc, MOVE_SRC_INFIFO_CL | MOVE_DEST_OUTFIFO |
|
|
MOVE_AUX_LS);
|
|
|
|
/* Write ICV */
|
|
append_seq_store(desc, icvsize, LDST_CLASS_2_CCB |
|
|
LDST_SRCDST_BYTE_CONTEXT);
|
|
|
|
#ifdef DEBUG
|
|
print_hex_dump(KERN_ERR,
|
|
"aead null enc shdesc@" __stringify(__LINE__)": ",
|
|
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(cnstr_shdsc_aead_null_encap);
|
|
|
|
/**
|
|
* cnstr_shdsc_aead_null_decap - IPSec ESP decapsulation shared descriptor
|
|
* (non-protocol) with no (null) decryption.
|
|
* @desc: pointer to buffer used for descriptor construction
|
|
* @adata: pointer to authentication transform definitions.
|
|
* A split key is required for SEC Era < 6; the size of the split key
|
|
* is specified in this case. Valid algorithm values - one of
|
|
* OP_ALG_ALGSEL_{MD5, SHA1, SHA224, SHA256, SHA384, SHA512} ANDed
|
|
* with OP_ALG_AAI_HMAC_PRECOMP.
|
|
* @icvsize: integrity check value (ICV) size (truncated or full)
|
|
* @era: SEC Era
|
|
*/
|
|
void cnstr_shdsc_aead_null_decap(u32 * const desc, struct alginfo *adata,
|
|
unsigned int icvsize, int era)
|
|
{
|
|
u32 *key_jump_cmd, *read_move_cmd, *write_move_cmd, *jump_cmd;
|
|
|
|
init_sh_desc(desc, HDR_SHARE_SERIAL);
|
|
|
|
/* Skip if already shared */
|
|
key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
|
|
JUMP_COND_SHRD);
|
|
if (era < 6) {
|
|
if (adata->key_inline)
|
|
append_key_as_imm(desc, adata->key_virt,
|
|
adata->keylen_pad, adata->keylen,
|
|
CLASS_2 | KEY_DEST_MDHA_SPLIT |
|
|
KEY_ENC);
|
|
else
|
|
append_key(desc, adata->key_dma, adata->keylen,
|
|
CLASS_2 | KEY_DEST_MDHA_SPLIT | KEY_ENC);
|
|
} else {
|
|
append_proto_dkp(desc, adata);
|
|
}
|
|
set_jump_tgt_here(desc, key_jump_cmd);
|
|
|
|
/* Class 2 operation */
|
|
append_operation(desc, adata->algtype | OP_ALG_AS_INITFINAL |
|
|
OP_ALG_DECRYPT | OP_ALG_ICV_ON);
|
|
|
|
/* assoclen + cryptlen = seqoutlen */
|
|
append_math_sub(desc, REG2, SEQOUTLEN, REG0, CAAM_CMD_SZ);
|
|
|
|
/* Prepare to read and write cryptlen + assoclen bytes */
|
|
append_math_add(desc, VARSEQINLEN, ZERO, REG2, CAAM_CMD_SZ);
|
|
append_math_add(desc, VARSEQOUTLEN, ZERO, REG2, CAAM_CMD_SZ);
|
|
|
|
/*
|
|
* MOVE_LEN opcode is not available in all SEC HW revisions,
|
|
* thus need to do some magic, i.e. self-patch the descriptor
|
|
* buffer.
|
|
*/
|
|
read_move_cmd = append_move(desc, MOVE_SRC_DESCBUF |
|
|
MOVE_DEST_MATH2 |
|
|
(0x6 << MOVE_LEN_SHIFT));
|
|
write_move_cmd = append_move(desc, MOVE_SRC_MATH2 |
|
|
MOVE_DEST_DESCBUF |
|
|
MOVE_WAITCOMP |
|
|
(0x8 << MOVE_LEN_SHIFT));
|
|
|
|
/* Read and write cryptlen bytes */
|
|
aead_append_src_dst(desc, FIFOLD_TYPE_MSG | FIFOLD_TYPE_FLUSH1);
|
|
|
|
/*
|
|
* Insert a NOP here, since we need at least 4 instructions between
|
|
* code patching the descriptor buffer and the location being patched.
|
|
*/
|
|
jump_cmd = append_jump(desc, JUMP_TEST_ALL);
|
|
set_jump_tgt_here(desc, jump_cmd);
|
|
|
|
set_move_tgt_here(desc, read_move_cmd);
|
|
set_move_tgt_here(desc, write_move_cmd);
|
|
append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
|
|
append_move(desc, MOVE_SRC_INFIFO_CL | MOVE_DEST_OUTFIFO |
|
|
MOVE_AUX_LS);
|
|
append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
|
|
|
|
/* Load ICV */
|
|
append_seq_fifo_load(desc, icvsize, FIFOLD_CLASS_CLASS2 |
|
|
FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_ICV);
|
|
|
|
#ifdef DEBUG
|
|
print_hex_dump(KERN_ERR,
|
|
"aead null dec shdesc@" __stringify(__LINE__)": ",
|
|
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(cnstr_shdsc_aead_null_decap);
|
|
|
|
static void init_sh_desc_key_aead(u32 * const desc,
|
|
struct alginfo * const cdata,
|
|
struct alginfo * const adata,
|
|
const bool is_rfc3686, u32 *nonce, int era)
|
|
{
|
|
u32 *key_jump_cmd;
|
|
unsigned int enckeylen = cdata->keylen;
|
|
|
|
/* Note: Context registers are saved. */
|
|
init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
|
|
|
|
/* Skip if already shared */
|
|
key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
|
|
JUMP_COND_SHRD);
|
|
|
|
/*
|
|
* RFC3686 specific:
|
|
* | key = {AUTH_KEY, ENC_KEY, NONCE}
|
|
* | enckeylen = encryption key size + nonce size
|
|
*/
|
|
if (is_rfc3686)
|
|
enckeylen -= CTR_RFC3686_NONCE_SIZE;
|
|
|
|
if (era < 6) {
|
|
if (adata->key_inline)
|
|
append_key_as_imm(desc, adata->key_virt,
|
|
adata->keylen_pad, adata->keylen,
|
|
CLASS_2 | KEY_DEST_MDHA_SPLIT |
|
|
KEY_ENC);
|
|
else
|
|
append_key(desc, adata->key_dma, adata->keylen,
|
|
CLASS_2 | KEY_DEST_MDHA_SPLIT | KEY_ENC);
|
|
} else {
|
|
append_proto_dkp(desc, adata);
|
|
}
|
|
|
|
if (cdata->key_inline)
|
|
append_key_as_imm(desc, cdata->key_virt, enckeylen,
|
|
enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
|
|
else
|
|
append_key(desc, cdata->key_dma, enckeylen, CLASS_1 |
|
|
KEY_DEST_CLASS_REG);
|
|
|
|
/* Load Counter into CONTEXT1 reg */
|
|
if (is_rfc3686) {
|
|
append_load_as_imm(desc, nonce, CTR_RFC3686_NONCE_SIZE,
|
|
LDST_CLASS_IND_CCB |
|
|
LDST_SRCDST_BYTE_OUTFIFO | LDST_IMM);
|
|
append_move(desc,
|
|
MOVE_SRC_OUTFIFO |
|
|
MOVE_DEST_CLASS1CTX |
|
|
(16 << MOVE_OFFSET_SHIFT) |
|
|
(CTR_RFC3686_NONCE_SIZE << MOVE_LEN_SHIFT));
|
|
}
|
|
|
|
set_jump_tgt_here(desc, key_jump_cmd);
|
|
}
|
|
|
|
/**
|
|
* cnstr_shdsc_aead_encap - IPSec ESP encapsulation shared descriptor
|
|
* (non-protocol).
|
|
* @desc: pointer to buffer used for descriptor construction
|
|
* @cdata: pointer to block cipher transform definitions
|
|
* Valid algorithm values - one of OP_ALG_ALGSEL_{AES, DES, 3DES} ANDed
|
|
* with OP_ALG_AAI_CBC or OP_ALG_AAI_CTR_MOD128.
|
|
* @adata: pointer to authentication transform definitions.
|
|
* A split key is required for SEC Era < 6; the size of the split key
|
|
* is specified in this case. 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
|
|
* @era: SEC Era
|
|
*/
|
|
void cnstr_shdsc_aead_encap(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, const bool is_qi,
|
|
int era)
|
|
{
|
|
/* Note: Context registers are saved. */
|
|
init_sh_desc_key_aead(desc, cdata, adata, is_rfc3686, nonce, era);
|
|
|
|
/* Class 2 operation */
|
|
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 */
|
|
if (is_qi || era < 3) {
|
|
append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
|
|
append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
|
|
} else {
|
|
append_math_add(desc, VARSEQINLEN, ZERO, DPOVRD, CAAM_CMD_SZ);
|
|
append_math_add(desc, VARSEQOUTLEN, ZERO, DPOVRD, CAAM_CMD_SZ);
|
|
}
|
|
|
|
/* Skip assoc data */
|
|
append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
|
|
|
|
/* read assoc before reading payload */
|
|
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
|
|
FIFOLDST_VLF);
|
|
|
|
/* Load Counter into CONTEXT1 reg */
|
|
if (is_rfc3686)
|
|
append_load_imm_be32(desc, 1, LDST_IMM | LDST_CLASS_1_CCB |
|
|
LDST_SRCDST_BYTE_CONTEXT |
|
|
((ctx1_iv_off + CTR_RFC3686_IV_SIZE) <<
|
|
LDST_OFFSET_SHIFT));
|
|
|
|
/* Class 1 operation */
|
|
append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
|
|
OP_ALG_ENCRYPT);
|
|
|
|
/* Read and write cryptlen bytes */
|
|
append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
|
|
append_math_add(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
|
|
aead_append_src_dst(desc, FIFOLD_TYPE_MSG1OUT2);
|
|
|
|
/* Write ICV */
|
|
append_seq_store(desc, icvsize, LDST_CLASS_2_CCB |
|
|
LDST_SRCDST_BYTE_CONTEXT);
|
|
|
|
#ifdef DEBUG
|
|
print_hex_dump(KERN_ERR, "aead enc shdesc@" __stringify(__LINE__)": ",
|
|
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(cnstr_shdsc_aead_encap);
|
|
|
|
/**
|
|
* cnstr_shdsc_aead_decap - IPSec ESP decapsulation shared descriptor
|
|
* (non-protocol).
|
|
* @desc: pointer to buffer used for descriptor construction
|
|
* @cdata: pointer to block cipher transform definitions
|
|
* Valid algorithm values - one of OP_ALG_ALGSEL_{AES, DES, 3DES} ANDed
|
|
* with OP_ALG_AAI_CBC or OP_ALG_AAI_CTR_MOD128.
|
|
* @adata: pointer to authentication transform definitions.
|
|
* A split key is required for SEC Era < 6; the size of the split key
|
|
* is specified in this case. 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
|
|
* @era: SEC Era
|
|
*/
|
|
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 bool is_qi, int era)
|
|
{
|
|
/* Note: Context registers are saved. */
|
|
init_sh_desc_key_aead(desc, cdata, adata, is_rfc3686, nonce, era);
|
|
|
|
/* Class 2 operation */
|
|
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 */
|
|
if (is_qi || era < 3) {
|
|
append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
|
|
if (geniv)
|
|
append_math_add_imm_u32(desc, VARSEQOUTLEN, REG3, IMM,
|
|
ivsize);
|
|
else
|
|
append_math_add(desc, VARSEQOUTLEN, ZERO, REG3,
|
|
CAAM_CMD_SZ);
|
|
} else {
|
|
append_math_add(desc, VARSEQINLEN, ZERO, DPOVRD, CAAM_CMD_SZ);
|
|
if (geniv)
|
|
append_math_add_imm_u32(desc, VARSEQOUTLEN, DPOVRD, IMM,
|
|
ivsize);
|
|
else
|
|
append_math_add(desc, VARSEQOUTLEN, ZERO, DPOVRD,
|
|
CAAM_CMD_SZ);
|
|
}
|
|
|
|
/* Skip assoc data */
|
|
append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
|
|
|
|
/* read assoc before reading payload */
|
|
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
|
|
KEY_VLF);
|
|
|
|
if (geniv) {
|
|
append_seq_load(desc, ivsize, LDST_CLASS_1_CCB |
|
|
LDST_SRCDST_BYTE_CONTEXT |
|
|
(ctx1_iv_off << LDST_OFFSET_SHIFT));
|
|
append_move(desc, MOVE_SRC_CLASS1CTX | MOVE_DEST_CLASS2INFIFO |
|
|
(ctx1_iv_off << MOVE_OFFSET_SHIFT) | ivsize);
|
|
}
|
|
|
|
/* Load Counter into CONTEXT1 reg */
|
|
if (is_rfc3686)
|
|
append_load_imm_be32(desc, 1, LDST_IMM | LDST_CLASS_1_CCB |
|
|
LDST_SRCDST_BYTE_CONTEXT |
|
|
((ctx1_iv_off + CTR_RFC3686_IV_SIZE) <<
|
|
LDST_OFFSET_SHIFT));
|
|
|
|
/* Choose operation */
|
|
if (ctx1_iv_off)
|
|
append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
|
|
OP_ALG_DECRYPT);
|
|
else
|
|
append_dec_op1(desc, cdata->algtype);
|
|
|
|
/* Read and write cryptlen bytes */
|
|
append_math_add(desc, VARSEQINLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
|
|
append_math_add(desc, VARSEQOUTLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
|
|
aead_append_src_dst(desc, FIFOLD_TYPE_MSG);
|
|
|
|
/* Load ICV */
|
|
append_seq_fifo_load(desc, icvsize, FIFOLD_CLASS_CLASS2 |
|
|
FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_ICV);
|
|
|
|
#ifdef DEBUG
|
|
print_hex_dump(KERN_ERR, "aead dec shdesc@" __stringify(__LINE__)": ",
|
|
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(cnstr_shdsc_aead_decap);
|
|
|
|
/**
|
|
* cnstr_shdsc_aead_givencap - IPSec ESP encapsulation shared descriptor
|
|
* (non-protocol) with HW-generated initialization
|
|
* vector.
|
|
* @desc: pointer to buffer used for descriptor construction
|
|
* @cdata: pointer to block cipher transform definitions
|
|
* Valid algorithm values - one of OP_ALG_ALGSEL_{AES, DES, 3DES} ANDed
|
|
* with OP_ALG_AAI_CBC or OP_ALG_AAI_CTR_MOD128.
|
|
* @adata: pointer to authentication transform definitions.
|
|
* A split key is required for SEC Era < 6; the size of the split key
|
|
* is specified in this case. 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
|
|
* @era: SEC Era
|
|
*/
|
|
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,
|
|
const bool is_qi, int era)
|
|
{
|
|
u32 geniv, moveiv;
|
|
|
|
/* Note: Context registers are saved. */
|
|
init_sh_desc_key_aead(desc, cdata, adata, is_rfc3686, nonce, era);
|
|
|
|
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 |
|
|
NFIFOENTRY_DTYPE_MSG | NFIFOENTRY_LC1 |
|
|
NFIFOENTRY_PTYPE_RND | (ivsize << NFIFOENTRY_DLEN_SHIFT);
|
|
append_load_imm_u32(desc, geniv, LDST_CLASS_IND_CCB |
|
|
LDST_SRCDST_WORD_INFO_FIFO | LDST_IMM);
|
|
append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
|
|
append_move(desc, MOVE_WAITCOMP |
|
|
MOVE_SRC_INFIFO | MOVE_DEST_CLASS1CTX |
|
|
(ctx1_iv_off << MOVE_OFFSET_SHIFT) |
|
|
(ivsize << MOVE_LEN_SHIFT));
|
|
append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
|
|
|
|
copy_iv:
|
|
/* Copy IV to class 1 context */
|
|
append_move(desc, MOVE_SRC_CLASS1CTX | MOVE_DEST_OUTFIFO |
|
|
(ctx1_iv_off << MOVE_OFFSET_SHIFT) |
|
|
(ivsize << MOVE_LEN_SHIFT));
|
|
|
|
/* Return to encryption */
|
|
append_operation(desc, adata->algtype | OP_ALG_AS_INITFINAL |
|
|
OP_ALG_ENCRYPT);
|
|
|
|
/* Read and write assoclen bytes */
|
|
if (is_qi || era < 3) {
|
|
append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
|
|
append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
|
|
} else {
|
|
append_math_add(desc, VARSEQINLEN, ZERO, DPOVRD, CAAM_CMD_SZ);
|
|
append_math_add(desc, VARSEQOUTLEN, ZERO, DPOVRD, CAAM_CMD_SZ);
|
|
}
|
|
|
|
/* Skip assoc data */
|
|
append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
|
|
|
|
/* read assoc before reading payload */
|
|
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
|
|
KEY_VLF);
|
|
|
|
/* Copy iv from outfifo to class 2 fifo */
|
|
moveiv = NFIFOENTRY_STYPE_OFIFO | NFIFOENTRY_DEST_CLASS2 |
|
|
NFIFOENTRY_DTYPE_MSG | (ivsize << NFIFOENTRY_DLEN_SHIFT);
|
|
append_load_imm_u32(desc, moveiv, LDST_CLASS_IND_CCB |
|
|
LDST_SRCDST_WORD_INFO_FIFO | LDST_IMM);
|
|
append_load_imm_u32(desc, ivsize, LDST_CLASS_2_CCB |
|
|
LDST_SRCDST_WORD_DATASZ_REG | LDST_IMM);
|
|
|
|
/* Load Counter into CONTEXT1 reg */
|
|
if (is_rfc3686)
|
|
append_load_imm_be32(desc, 1, LDST_IMM | LDST_CLASS_1_CCB |
|
|
LDST_SRCDST_BYTE_CONTEXT |
|
|
((ctx1_iv_off + CTR_RFC3686_IV_SIZE) <<
|
|
LDST_OFFSET_SHIFT));
|
|
|
|
/* Class 1 operation */
|
|
append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
|
|
OP_ALG_ENCRYPT);
|
|
|
|
/* Will write ivsize + cryptlen */
|
|
append_math_add(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
|
|
|
|
/* Not need to reload iv */
|
|
append_seq_fifo_load(desc, ivsize,
|
|
FIFOLD_CLASS_SKIP);
|
|
|
|
/* Will read cryptlen */
|
|
append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
|
|
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH | KEY_VLF |
|
|
FIFOLD_TYPE_MSG1OUT2 | FIFOLD_TYPE_LASTBOTH);
|
|
append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF);
|
|
|
|
/* Write ICV */
|
|
append_seq_store(desc, icvsize, LDST_CLASS_2_CCB |
|
|
LDST_SRCDST_BYTE_CONTEXT);
|
|
|
|
#ifdef DEBUG
|
|
print_hex_dump(KERN_ERR,
|
|
"aead givenc shdesc@" __stringify(__LINE__)": ",
|
|
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(cnstr_shdsc_aead_givencap);
|
|
|
|
/**
|
|
* cnstr_shdsc_gcm_encap - gcm encapsulation shared descriptor
|
|
* @desc: pointer to buffer used for descriptor construction
|
|
* @cdata: pointer to block cipher transform definitions
|
|
* Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_GCM.
|
|
* @icvsize: integrity check value (ICV) size (truncated or full)
|
|
*/
|
|
void cnstr_shdsc_gcm_encap(u32 * const desc, struct alginfo *cdata,
|
|
unsigned int icvsize)
|
|
{
|
|
u32 *key_jump_cmd, *zero_payload_jump_cmd, *zero_assoc_jump_cmd1,
|
|
*zero_assoc_jump_cmd2;
|
|
|
|
init_sh_desc(desc, HDR_SHARE_SERIAL);
|
|
|
|
/* skip key loading if they are loaded due to sharing */
|
|
key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
|
|
JUMP_COND_SHRD);
|
|
if (cdata->key_inline)
|
|
append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
|
|
cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
|
|
else
|
|
append_key(desc, cdata->key_dma, cdata->keylen, CLASS_1 |
|
|
KEY_DEST_CLASS_REG);
|
|
set_jump_tgt_here(desc, key_jump_cmd);
|
|
|
|
/* class 1 operation */
|
|
append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
|
|
OP_ALG_ENCRYPT);
|
|
|
|
/* if assoclen + cryptlen is ZERO, skip to ICV write */
|
|
append_math_sub(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
|
|
zero_assoc_jump_cmd2 = append_jump(desc, JUMP_TEST_ALL |
|
|
JUMP_COND_MATH_Z);
|
|
|
|
/* if assoclen is ZERO, skip reading the assoc data */
|
|
append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
|
|
zero_assoc_jump_cmd1 = append_jump(desc, JUMP_TEST_ALL |
|
|
JUMP_COND_MATH_Z);
|
|
|
|
append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
|
|
|
|
/* skip assoc data */
|
|
append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
|
|
|
|
/* cryptlen = seqinlen - assoclen */
|
|
append_math_sub(desc, VARSEQOUTLEN, SEQINLEN, REG3, CAAM_CMD_SZ);
|
|
|
|
/* if cryptlen is ZERO jump to zero-payload commands */
|
|
zero_payload_jump_cmd = append_jump(desc, JUMP_TEST_ALL |
|
|
JUMP_COND_MATH_Z);
|
|
|
|
/* read assoc data */
|
|
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
|
|
FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1);
|
|
set_jump_tgt_here(desc, zero_assoc_jump_cmd1);
|
|
|
|
append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
|
|
|
|
/* write encrypted data */
|
|
append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF);
|
|
|
|
/* read payload data */
|
|
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
|
|
FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1);
|
|
|
|
/* jump the zero-payload commands */
|
|
append_jump(desc, JUMP_TEST_ALL | 2);
|
|
|
|
/* zero-payload commands */
|
|
set_jump_tgt_here(desc, zero_payload_jump_cmd);
|
|
|
|
/* read assoc data */
|
|
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
|
|
FIFOLD_TYPE_AAD | FIFOLD_TYPE_LAST1);
|
|
|
|
/* There is no input data */
|
|
set_jump_tgt_here(desc, zero_assoc_jump_cmd2);
|
|
|
|
/* write ICV */
|
|
append_seq_store(desc, icvsize, LDST_CLASS_1_CCB |
|
|
LDST_SRCDST_BYTE_CONTEXT);
|
|
|
|
#ifdef DEBUG
|
|
print_hex_dump(KERN_ERR, "gcm enc shdesc@" __stringify(__LINE__)": ",
|
|
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(cnstr_shdsc_gcm_encap);
|
|
|
|
/**
|
|
* cnstr_shdsc_gcm_decap - gcm decapsulation shared descriptor
|
|
* @desc: pointer to buffer used for descriptor construction
|
|
* @cdata: pointer to block cipher transform definitions
|
|
* Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_GCM.
|
|
* @icvsize: integrity check value (ICV) size (truncated or full)
|
|
*/
|
|
void cnstr_shdsc_gcm_decap(u32 * const desc, struct alginfo *cdata,
|
|
unsigned int icvsize)
|
|
{
|
|
u32 *key_jump_cmd, *zero_payload_jump_cmd, *zero_assoc_jump_cmd1;
|
|
|
|
init_sh_desc(desc, HDR_SHARE_SERIAL);
|
|
|
|
/* skip key loading if they are loaded due to sharing */
|
|
key_jump_cmd = append_jump(desc, JUMP_JSL |
|
|
JUMP_TEST_ALL | JUMP_COND_SHRD);
|
|
if (cdata->key_inline)
|
|
append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
|
|
cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
|
|
else
|
|
append_key(desc, cdata->key_dma, cdata->keylen, CLASS_1 |
|
|
KEY_DEST_CLASS_REG);
|
|
set_jump_tgt_here(desc, key_jump_cmd);
|
|
|
|
/* class 1 operation */
|
|
append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
|
|
OP_ALG_DECRYPT | OP_ALG_ICV_ON);
|
|
|
|
/* if assoclen is ZERO, skip reading the assoc data */
|
|
append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
|
|
zero_assoc_jump_cmd1 = append_jump(desc, JUMP_TEST_ALL |
|
|
JUMP_COND_MATH_Z);
|
|
|
|
append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
|
|
|
|
/* skip assoc data */
|
|
append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
|
|
|
|
/* read assoc data */
|
|
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
|
|
FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1);
|
|
|
|
set_jump_tgt_here(desc, zero_assoc_jump_cmd1);
|
|
|
|
/* cryptlen = seqoutlen - assoclen */
|
|
append_math_sub(desc, VARSEQINLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
|
|
|
|
/* jump to zero-payload command if cryptlen is zero */
|
|
zero_payload_jump_cmd = append_jump(desc, JUMP_TEST_ALL |
|
|
JUMP_COND_MATH_Z);
|
|
|
|
append_math_sub(desc, VARSEQOUTLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
|
|
|
|
/* store encrypted data */
|
|
append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF);
|
|
|
|
/* read payload data */
|
|
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
|
|
FIFOLD_TYPE_MSG | FIFOLD_TYPE_FLUSH1);
|
|
|
|
/* zero-payload command */
|
|
set_jump_tgt_here(desc, zero_payload_jump_cmd);
|
|
|
|
/* read ICV */
|
|
append_seq_fifo_load(desc, icvsize, FIFOLD_CLASS_CLASS1 |
|
|
FIFOLD_TYPE_ICV | FIFOLD_TYPE_LAST1);
|
|
|
|
#ifdef DEBUG
|
|
print_hex_dump(KERN_ERR, "gcm dec shdesc@" __stringify(__LINE__)": ",
|
|
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(cnstr_shdsc_gcm_decap);
|
|
|
|
/**
|
|
* cnstr_shdsc_rfc4106_encap - IPSec ESP gcm encapsulation shared descriptor
|
|
* (non-protocol).
|
|
* @desc: pointer to buffer used for descriptor construction
|
|
* @cdata: pointer to block cipher transform definitions
|
|
* Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_GCM.
|
|
* @icvsize: integrity check value (ICV) size (truncated or full)
|
|
*/
|
|
void cnstr_shdsc_rfc4106_encap(u32 * const desc, struct alginfo *cdata,
|
|
unsigned int icvsize)
|
|
{
|
|
u32 *key_jump_cmd;
|
|
|
|
init_sh_desc(desc, HDR_SHARE_SERIAL);
|
|
|
|
/* Skip key loading if it is loaded due to sharing */
|
|
key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
|
|
JUMP_COND_SHRD);
|
|
if (cdata->key_inline)
|
|
append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
|
|
cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
|
|
else
|
|
append_key(desc, cdata->key_dma, cdata->keylen, CLASS_1 |
|
|
KEY_DEST_CLASS_REG);
|
|
set_jump_tgt_here(desc, key_jump_cmd);
|
|
|
|
/* Class 1 operation */
|
|
append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
|
|
OP_ALG_ENCRYPT);
|
|
|
|
append_math_sub_imm_u32(desc, VARSEQINLEN, REG3, IMM, 8);
|
|
append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
|
|
|
|
/* Read assoc data */
|
|
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
|
|
FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1);
|
|
|
|
/* Skip IV */
|
|
append_seq_fifo_load(desc, 8, FIFOLD_CLASS_SKIP);
|
|
|
|
/* Will read cryptlen bytes */
|
|
append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
|
|
|
|
/* Workaround for erratum A-005473 (simultaneous SEQ FIFO skips) */
|
|
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_MSG);
|
|
|
|
/* Skip assoc data */
|
|
append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
|
|
|
|
/* cryptlen = seqoutlen - assoclen */
|
|
append_math_sub(desc, VARSEQOUTLEN, VARSEQINLEN, REG0, CAAM_CMD_SZ);
|
|
|
|
/* Write encrypted data */
|
|
append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF);
|
|
|
|
/* Read payload data */
|
|
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
|
|
FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1);
|
|
|
|
/* Write ICV */
|
|
append_seq_store(desc, icvsize, LDST_CLASS_1_CCB |
|
|
LDST_SRCDST_BYTE_CONTEXT);
|
|
|
|
#ifdef DEBUG
|
|
print_hex_dump(KERN_ERR,
|
|
"rfc4106 enc shdesc@" __stringify(__LINE__)": ",
|
|
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(cnstr_shdsc_rfc4106_encap);
|
|
|
|
/**
|
|
* cnstr_shdsc_rfc4106_decap - IPSec ESP gcm decapsulation shared descriptor
|
|
* (non-protocol).
|
|
* @desc: pointer to buffer used for descriptor construction
|
|
* @cdata: pointer to block cipher transform definitions
|
|
* Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_GCM.
|
|
* @icvsize: integrity check value (ICV) size (truncated or full)
|
|
*/
|
|
void cnstr_shdsc_rfc4106_decap(u32 * const desc, struct alginfo *cdata,
|
|
unsigned int icvsize)
|
|
{
|
|
u32 *key_jump_cmd;
|
|
|
|
init_sh_desc(desc, HDR_SHARE_SERIAL);
|
|
|
|
/* Skip key loading if it is loaded due to sharing */
|
|
key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
|
|
JUMP_COND_SHRD);
|
|
if (cdata->key_inline)
|
|
append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
|
|
cdata->keylen, CLASS_1 |
|
|
KEY_DEST_CLASS_REG);
|
|
else
|
|
append_key(desc, cdata->key_dma, cdata->keylen, CLASS_1 |
|
|
KEY_DEST_CLASS_REG);
|
|
set_jump_tgt_here(desc, key_jump_cmd);
|
|
|
|
/* Class 1 operation */
|
|
append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
|
|
OP_ALG_DECRYPT | OP_ALG_ICV_ON);
|
|
|
|
append_math_sub_imm_u32(desc, VARSEQINLEN, REG3, IMM, 8);
|
|
append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
|
|
|
|
/* Read assoc data */
|
|
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
|
|
FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1);
|
|
|
|
/* Skip IV */
|
|
append_seq_fifo_load(desc, 8, FIFOLD_CLASS_SKIP);
|
|
|
|
/* Will read cryptlen bytes */
|
|
append_math_sub(desc, VARSEQINLEN, SEQOUTLEN, REG3, CAAM_CMD_SZ);
|
|
|
|
/* Workaround for erratum A-005473 (simultaneous SEQ FIFO skips) */
|
|
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_MSG);
|
|
|
|
/* Skip assoc data */
|
|
append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
|
|
|
|
/* Will write cryptlen bytes */
|
|
append_math_sub(desc, VARSEQOUTLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
|
|
|
|
/* Store payload data */
|
|
append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF);
|
|
|
|
/* Read encrypted data */
|
|
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
|
|
FIFOLD_TYPE_MSG | FIFOLD_TYPE_FLUSH1);
|
|
|
|
/* Read ICV */
|
|
append_seq_fifo_load(desc, icvsize, FIFOLD_CLASS_CLASS1 |
|
|
FIFOLD_TYPE_ICV | FIFOLD_TYPE_LAST1);
|
|
|
|
#ifdef DEBUG
|
|
print_hex_dump(KERN_ERR,
|
|
"rfc4106 dec shdesc@" __stringify(__LINE__)": ",
|
|
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(cnstr_shdsc_rfc4106_decap);
|
|
|
|
/**
|
|
* cnstr_shdsc_rfc4543_encap - IPSec ESP gmac encapsulation shared descriptor
|
|
* (non-protocol).
|
|
* @desc: pointer to buffer used for descriptor construction
|
|
* @cdata: pointer to block cipher transform definitions
|
|
* Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_GCM.
|
|
* @icvsize: integrity check value (ICV) size (truncated or full)
|
|
*/
|
|
void cnstr_shdsc_rfc4543_encap(u32 * const desc, struct alginfo *cdata,
|
|
unsigned int icvsize)
|
|
{
|
|
u32 *key_jump_cmd, *read_move_cmd, *write_move_cmd;
|
|
|
|
init_sh_desc(desc, HDR_SHARE_SERIAL);
|
|
|
|
/* Skip key loading if it is loaded due to sharing */
|
|
key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
|
|
JUMP_COND_SHRD);
|
|
if (cdata->key_inline)
|
|
append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
|
|
cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
|
|
else
|
|
append_key(desc, cdata->key_dma, cdata->keylen, CLASS_1 |
|
|
KEY_DEST_CLASS_REG);
|
|
set_jump_tgt_here(desc, key_jump_cmd);
|
|
|
|
/* Class 1 operation */
|
|
append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
|
|
OP_ALG_ENCRYPT);
|
|
|
|
/* assoclen + cryptlen = seqinlen */
|
|
append_math_sub(desc, REG3, SEQINLEN, REG0, CAAM_CMD_SZ);
|
|
|
|
/*
|
|
* MOVE_LEN opcode is not available in all SEC HW revisions,
|
|
* thus need to do some magic, i.e. self-patch the descriptor
|
|
* buffer.
|
|
*/
|
|
read_move_cmd = append_move(desc, MOVE_SRC_DESCBUF | MOVE_DEST_MATH3 |
|
|
(0x6 << MOVE_LEN_SHIFT));
|
|
write_move_cmd = append_move(desc, MOVE_SRC_MATH3 | MOVE_DEST_DESCBUF |
|
|
(0x8 << MOVE_LEN_SHIFT));
|
|
|
|
/* Will read assoclen + cryptlen bytes */
|
|
append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
|
|
|
|
/* Will write assoclen + cryptlen bytes */
|
|
append_math_sub(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
|
|
|
|
/* Read and write assoclen + cryptlen bytes */
|
|
aead_append_src_dst(desc, FIFOLD_TYPE_AAD);
|
|
|
|
set_move_tgt_here(desc, read_move_cmd);
|
|
set_move_tgt_here(desc, write_move_cmd);
|
|
append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
|
|
/* Move payload data to OFIFO */
|
|
append_move(desc, MOVE_SRC_INFIFO_CL | MOVE_DEST_OUTFIFO);
|
|
|
|
/* Write ICV */
|
|
append_seq_store(desc, icvsize, LDST_CLASS_1_CCB |
|
|
LDST_SRCDST_BYTE_CONTEXT);
|
|
|
|
#ifdef DEBUG
|
|
print_hex_dump(KERN_ERR,
|
|
"rfc4543 enc shdesc@" __stringify(__LINE__)": ",
|
|
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(cnstr_shdsc_rfc4543_encap);
|
|
|
|
/**
|
|
* cnstr_shdsc_rfc4543_decap - IPSec ESP gmac decapsulation shared descriptor
|
|
* (non-protocol).
|
|
* @desc: pointer to buffer used for descriptor construction
|
|
* @cdata: pointer to block cipher transform definitions
|
|
* Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_GCM.
|
|
* @icvsize: integrity check value (ICV) size (truncated or full)
|
|
*/
|
|
void cnstr_shdsc_rfc4543_decap(u32 * const desc, struct alginfo *cdata,
|
|
unsigned int icvsize)
|
|
{
|
|
u32 *key_jump_cmd, *read_move_cmd, *write_move_cmd;
|
|
|
|
init_sh_desc(desc, HDR_SHARE_SERIAL);
|
|
|
|
/* Skip key loading if it is loaded due to sharing */
|
|
key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
|
|
JUMP_COND_SHRD);
|
|
if (cdata->key_inline)
|
|
append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
|
|
cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
|
|
else
|
|
append_key(desc, cdata->key_dma, cdata->keylen, CLASS_1 |
|
|
KEY_DEST_CLASS_REG);
|
|
set_jump_tgt_here(desc, key_jump_cmd);
|
|
|
|
/* Class 1 operation */
|
|
append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
|
|
OP_ALG_DECRYPT | OP_ALG_ICV_ON);
|
|
|
|
/* assoclen + cryptlen = seqoutlen */
|
|
append_math_sub(desc, REG3, SEQOUTLEN, REG0, CAAM_CMD_SZ);
|
|
|
|
/*
|
|
* MOVE_LEN opcode is not available in all SEC HW revisions,
|
|
* thus need to do some magic, i.e. self-patch the descriptor
|
|
* buffer.
|
|
*/
|
|
read_move_cmd = append_move(desc, MOVE_SRC_DESCBUF | MOVE_DEST_MATH3 |
|
|
(0x6 << MOVE_LEN_SHIFT));
|
|
write_move_cmd = append_move(desc, MOVE_SRC_MATH3 | MOVE_DEST_DESCBUF |
|
|
(0x8 << MOVE_LEN_SHIFT));
|
|
|
|
/* Will read assoclen + cryptlen bytes */
|
|
append_math_sub(desc, VARSEQINLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
|
|
|
|
/* Will write assoclen + cryptlen bytes */
|
|
append_math_sub(desc, VARSEQOUTLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
|
|
|
|
/* Store payload data */
|
|
append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF);
|
|
|
|
/* In-snoop assoclen + cryptlen data */
|
|
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH | FIFOLDST_VLF |
|
|
FIFOLD_TYPE_AAD | FIFOLD_TYPE_LAST2FLUSH1);
|
|
|
|
set_move_tgt_here(desc, read_move_cmd);
|
|
set_move_tgt_here(desc, write_move_cmd);
|
|
append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
|
|
/* Move payload data to OFIFO */
|
|
append_move(desc, MOVE_SRC_INFIFO_CL | MOVE_DEST_OUTFIFO);
|
|
append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
|
|
|
|
/* Read ICV */
|
|
append_seq_fifo_load(desc, icvsize, FIFOLD_CLASS_CLASS1 |
|
|
FIFOLD_TYPE_ICV | FIFOLD_TYPE_LAST1);
|
|
|
|
#ifdef DEBUG
|
|
print_hex_dump(KERN_ERR,
|
|
"rfc4543 dec shdesc@" __stringify(__LINE__)": ",
|
|
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(cnstr_shdsc_rfc4543_decap);
|
|
|
|
/*
|
|
* For ablkcipher encrypt and decrypt, read from req->src and
|
|
* write to req->dst
|
|
*/
|
|
static inline void ablkcipher_append_src_dst(u32 *desc)
|
|
{
|
|
append_math_add(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
|
|
append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
|
|
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 |
|
|
KEY_VLF | FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1);
|
|
append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF);
|
|
}
|
|
|
|
/**
|
|
* cnstr_shdsc_ablkcipher_encap - ablkcipher encapsulation shared descriptor
|
|
* @desc: pointer to buffer used for descriptor construction
|
|
* @cdata: pointer to block cipher transform definitions
|
|
* Valid algorithm values - one of OP_ALG_ALGSEL_{AES, DES, 3DES} ANDed
|
|
* with OP_ALG_AAI_CBC or OP_ALG_AAI_CTR_MOD128.
|
|
* @ivsize: initialization vector size
|
|
* @is_rfc3686: true when ctr(aes) is wrapped by rfc3686 template
|
|
* @ctx1_iv_off: IV offset in CONTEXT1 register
|
|
*/
|
|
void cnstr_shdsc_ablkcipher_encap(u32 * const desc, struct alginfo *cdata,
|
|
unsigned int ivsize, const bool is_rfc3686,
|
|
const u32 ctx1_iv_off)
|
|
{
|
|
u32 *key_jump_cmd;
|
|
|
|
init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
|
|
/* Skip if already shared */
|
|
key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
|
|
JUMP_COND_SHRD);
|
|
|
|
/* Load class1 key only */
|
|
append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
|
|
cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
|
|
|
|
/* Load nonce into CONTEXT1 reg */
|
|
if (is_rfc3686) {
|
|
const u8 *nonce = cdata->key_virt + cdata->keylen;
|
|
|
|
append_load_as_imm(desc, nonce, CTR_RFC3686_NONCE_SIZE,
|
|
LDST_CLASS_IND_CCB |
|
|
LDST_SRCDST_BYTE_OUTFIFO | LDST_IMM);
|
|
append_move(desc, MOVE_WAITCOMP | MOVE_SRC_OUTFIFO |
|
|
MOVE_DEST_CLASS1CTX | (16 << MOVE_OFFSET_SHIFT) |
|
|
(CTR_RFC3686_NONCE_SIZE << MOVE_LEN_SHIFT));
|
|
}
|
|
|
|
set_jump_tgt_here(desc, key_jump_cmd);
|
|
|
|
/* Load iv */
|
|
append_seq_load(desc, ivsize, LDST_SRCDST_BYTE_CONTEXT |
|
|
LDST_CLASS_1_CCB | (ctx1_iv_off << LDST_OFFSET_SHIFT));
|
|
|
|
/* Load counter into CONTEXT1 reg */
|
|
if (is_rfc3686)
|
|
append_load_imm_be32(desc, 1, LDST_IMM | LDST_CLASS_1_CCB |
|
|
LDST_SRCDST_BYTE_CONTEXT |
|
|
((ctx1_iv_off + CTR_RFC3686_IV_SIZE) <<
|
|
LDST_OFFSET_SHIFT));
|
|
|
|
/* Load operation */
|
|
append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
|
|
OP_ALG_ENCRYPT);
|
|
|
|
/* Perform operation */
|
|
ablkcipher_append_src_dst(desc);
|
|
|
|
#ifdef DEBUG
|
|
print_hex_dump(KERN_ERR,
|
|
"ablkcipher enc shdesc@" __stringify(__LINE__)": ",
|
|
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(cnstr_shdsc_ablkcipher_encap);
|
|
|
|
/**
|
|
* cnstr_shdsc_ablkcipher_decap - ablkcipher decapsulation shared descriptor
|
|
* @desc: pointer to buffer used for descriptor construction
|
|
* @cdata: pointer to block cipher transform definitions
|
|
* Valid algorithm values - one of OP_ALG_ALGSEL_{AES, DES, 3DES} ANDed
|
|
* with OP_ALG_AAI_CBC or OP_ALG_AAI_CTR_MOD128.
|
|
* @ivsize: initialization vector size
|
|
* @is_rfc3686: true when ctr(aes) is wrapped by rfc3686 template
|
|
* @ctx1_iv_off: IV offset in CONTEXT1 register
|
|
*/
|
|
void cnstr_shdsc_ablkcipher_decap(u32 * const desc, struct alginfo *cdata,
|
|
unsigned int ivsize, const bool is_rfc3686,
|
|
const u32 ctx1_iv_off)
|
|
{
|
|
u32 *key_jump_cmd;
|
|
|
|
init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
|
|
/* Skip if already shared */
|
|
key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
|
|
JUMP_COND_SHRD);
|
|
|
|
/* Load class1 key only */
|
|
append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
|
|
cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
|
|
|
|
/* Load nonce into CONTEXT1 reg */
|
|
if (is_rfc3686) {
|
|
const u8 *nonce = cdata->key_virt + cdata->keylen;
|
|
|
|
append_load_as_imm(desc, nonce, CTR_RFC3686_NONCE_SIZE,
|
|
LDST_CLASS_IND_CCB |
|
|
LDST_SRCDST_BYTE_OUTFIFO | LDST_IMM);
|
|
append_move(desc, MOVE_WAITCOMP | MOVE_SRC_OUTFIFO |
|
|
MOVE_DEST_CLASS1CTX | (16 << MOVE_OFFSET_SHIFT) |
|
|
(CTR_RFC3686_NONCE_SIZE << MOVE_LEN_SHIFT));
|
|
}
|
|
|
|
set_jump_tgt_here(desc, key_jump_cmd);
|
|
|
|
/* load IV */
|
|
append_seq_load(desc, ivsize, LDST_SRCDST_BYTE_CONTEXT |
|
|
LDST_CLASS_1_CCB | (ctx1_iv_off << LDST_OFFSET_SHIFT));
|
|
|
|
/* Load counter into CONTEXT1 reg */
|
|
if (is_rfc3686)
|
|
append_load_imm_be32(desc, 1, LDST_IMM | LDST_CLASS_1_CCB |
|
|
LDST_SRCDST_BYTE_CONTEXT |
|
|
((ctx1_iv_off + CTR_RFC3686_IV_SIZE) <<
|
|
LDST_OFFSET_SHIFT));
|
|
|
|
/* Choose operation */
|
|
if (ctx1_iv_off)
|
|
append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
|
|
OP_ALG_DECRYPT);
|
|
else
|
|
append_dec_op1(desc, cdata->algtype);
|
|
|
|
/* Perform operation */
|
|
ablkcipher_append_src_dst(desc);
|
|
|
|
#ifdef DEBUG
|
|
print_hex_dump(KERN_ERR,
|
|
"ablkcipher dec shdesc@" __stringify(__LINE__)": ",
|
|
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(cnstr_shdsc_ablkcipher_decap);
|
|
|
|
/**
|
|
* cnstr_shdsc_ablkcipher_givencap - ablkcipher encapsulation shared descriptor
|
|
* with HW-generated initialization vector.
|
|
* @desc: pointer to buffer used for descriptor construction
|
|
* @cdata: pointer to block cipher transform definitions
|
|
* Valid algorithm values - one of OP_ALG_ALGSEL_{AES, DES, 3DES} ANDed
|
|
* with OP_ALG_AAI_CBC.
|
|
* @ivsize: initialization vector size
|
|
* @is_rfc3686: true when ctr(aes) is wrapped by rfc3686 template
|
|
* @ctx1_iv_off: IV offset in CONTEXT1 register
|
|
*/
|
|
void cnstr_shdsc_ablkcipher_givencap(u32 * const desc, struct alginfo *cdata,
|
|
unsigned int ivsize, const bool is_rfc3686,
|
|
const u32 ctx1_iv_off)
|
|
{
|
|
u32 *key_jump_cmd, geniv;
|
|
|
|
init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
|
|
/* Skip if already shared */
|
|
key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
|
|
JUMP_COND_SHRD);
|
|
|
|
/* Load class1 key only */
|
|
append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
|
|
cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
|
|
|
|
/* Load Nonce into CONTEXT1 reg */
|
|
if (is_rfc3686) {
|
|
const u8 *nonce = cdata->key_virt + cdata->keylen;
|
|
|
|
append_load_as_imm(desc, nonce, CTR_RFC3686_NONCE_SIZE,
|
|
LDST_CLASS_IND_CCB |
|
|
LDST_SRCDST_BYTE_OUTFIFO | LDST_IMM);
|
|
append_move(desc, MOVE_WAITCOMP | MOVE_SRC_OUTFIFO |
|
|
MOVE_DEST_CLASS1CTX | (16 << MOVE_OFFSET_SHIFT) |
|
|
(CTR_RFC3686_NONCE_SIZE << MOVE_LEN_SHIFT));
|
|
}
|
|
set_jump_tgt_here(desc, key_jump_cmd);
|
|
|
|
/* Generate IV */
|
|
geniv = NFIFOENTRY_STYPE_PAD | NFIFOENTRY_DEST_DECO |
|
|
NFIFOENTRY_DTYPE_MSG | NFIFOENTRY_LC1 | NFIFOENTRY_PTYPE_RND |
|
|
(ivsize << NFIFOENTRY_DLEN_SHIFT);
|
|
append_load_imm_u32(desc, geniv, LDST_CLASS_IND_CCB |
|
|
LDST_SRCDST_WORD_INFO_FIFO | LDST_IMM);
|
|
append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
|
|
append_move(desc, MOVE_WAITCOMP | MOVE_SRC_INFIFO |
|
|
MOVE_DEST_CLASS1CTX | (ivsize << MOVE_LEN_SHIFT) |
|
|
(ctx1_iv_off << MOVE_OFFSET_SHIFT));
|
|
append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
|
|
|
|
/* Copy generated IV to memory */
|
|
append_seq_store(desc, ivsize, LDST_SRCDST_BYTE_CONTEXT |
|
|
LDST_CLASS_1_CCB | (ctx1_iv_off << LDST_OFFSET_SHIFT));
|
|
|
|
/* Load Counter into CONTEXT1 reg */
|
|
if (is_rfc3686)
|
|
append_load_imm_be32(desc, 1, LDST_IMM | LDST_CLASS_1_CCB |
|
|
LDST_SRCDST_BYTE_CONTEXT |
|
|
((ctx1_iv_off + CTR_RFC3686_IV_SIZE) <<
|
|
LDST_OFFSET_SHIFT));
|
|
|
|
if (ctx1_iv_off)
|
|
append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | JUMP_COND_NCP |
|
|
(1 << JUMP_OFFSET_SHIFT));
|
|
|
|
/* Load operation */
|
|
append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
|
|
OP_ALG_ENCRYPT);
|
|
|
|
/* Perform operation */
|
|
ablkcipher_append_src_dst(desc);
|
|
|
|
#ifdef DEBUG
|
|
print_hex_dump(KERN_ERR,
|
|
"ablkcipher givenc shdesc@" __stringify(__LINE__) ": ",
|
|
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(cnstr_shdsc_ablkcipher_givencap);
|
|
|
|
/**
|
|
* cnstr_shdsc_xts_ablkcipher_encap - xts ablkcipher encapsulation shared
|
|
* descriptor
|
|
* @desc: pointer to buffer used for descriptor construction
|
|
* @cdata: pointer to block cipher transform definitions
|
|
* Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_XTS.
|
|
*/
|
|
void cnstr_shdsc_xts_ablkcipher_encap(u32 * const desc, struct alginfo *cdata)
|
|
{
|
|
__be64 sector_size = cpu_to_be64(512);
|
|
u32 *key_jump_cmd;
|
|
|
|
init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
|
|
/* Skip if already shared */
|
|
key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
|
|
JUMP_COND_SHRD);
|
|
|
|
/* Load class1 keys only */
|
|
append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
|
|
cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
|
|
|
|
/* Load sector size with index 40 bytes (0x28) */
|
|
append_load_as_imm(desc, (void *)§or_size, 8, LDST_CLASS_1_CCB |
|
|
LDST_SRCDST_BYTE_CONTEXT |
|
|
(0x28 << LDST_OFFSET_SHIFT));
|
|
|
|
set_jump_tgt_here(desc, key_jump_cmd);
|
|
|
|
/*
|
|
* create sequence for loading the sector index
|
|
* Upper 8B of IV - will be used as sector index
|
|
* Lower 8B of IV - will be discarded
|
|
*/
|
|
append_seq_load(desc, 8, LDST_SRCDST_BYTE_CONTEXT | LDST_CLASS_1_CCB |
|
|
(0x20 << LDST_OFFSET_SHIFT));
|
|
append_seq_fifo_load(desc, 8, FIFOLD_CLASS_SKIP);
|
|
|
|
/* Load operation */
|
|
append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
|
|
OP_ALG_ENCRYPT);
|
|
|
|
/* Perform operation */
|
|
ablkcipher_append_src_dst(desc);
|
|
|
|
#ifdef DEBUG
|
|
print_hex_dump(KERN_ERR,
|
|
"xts ablkcipher enc shdesc@" __stringify(__LINE__) ": ",
|
|
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(cnstr_shdsc_xts_ablkcipher_encap);
|
|
|
|
/**
|
|
* cnstr_shdsc_xts_ablkcipher_decap - xts ablkcipher decapsulation shared
|
|
* descriptor
|
|
* @desc: pointer to buffer used for descriptor construction
|
|
* @cdata: pointer to block cipher transform definitions
|
|
* Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_XTS.
|
|
*/
|
|
void cnstr_shdsc_xts_ablkcipher_decap(u32 * const desc, struct alginfo *cdata)
|
|
{
|
|
__be64 sector_size = cpu_to_be64(512);
|
|
u32 *key_jump_cmd;
|
|
|
|
init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
|
|
/* Skip if already shared */
|
|
key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
|
|
JUMP_COND_SHRD);
|
|
|
|
/* Load class1 key only */
|
|
append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
|
|
cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
|
|
|
|
/* Load sector size with index 40 bytes (0x28) */
|
|
append_load_as_imm(desc, (void *)§or_size, 8, LDST_CLASS_1_CCB |
|
|
LDST_SRCDST_BYTE_CONTEXT |
|
|
(0x28 << LDST_OFFSET_SHIFT));
|
|
|
|
set_jump_tgt_here(desc, key_jump_cmd);
|
|
|
|
/*
|
|
* create sequence for loading the sector index
|
|
* Upper 8B of IV - will be used as sector index
|
|
* Lower 8B of IV - will be discarded
|
|
*/
|
|
append_seq_load(desc, 8, LDST_SRCDST_BYTE_CONTEXT | LDST_CLASS_1_CCB |
|
|
(0x20 << LDST_OFFSET_SHIFT));
|
|
append_seq_fifo_load(desc, 8, FIFOLD_CLASS_SKIP);
|
|
|
|
/* Load operation */
|
|
append_dec_op1(desc, cdata->algtype);
|
|
|
|
/* Perform operation */
|
|
ablkcipher_append_src_dst(desc);
|
|
|
|
#ifdef DEBUG
|
|
print_hex_dump(KERN_ERR,
|
|
"xts ablkcipher dec shdesc@" __stringify(__LINE__) ": ",
|
|
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(cnstr_shdsc_xts_ablkcipher_decap);
|
|
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_DESCRIPTION("FSL CAAM descriptor support");
|
|
MODULE_AUTHOR("Freescale Semiconductor - NMG/STC");
|