[PATCH v2 11/12] crypto: caam - move caamalg shared descs in RTA library

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



aead shared descriptors are moved from caamalg in RTA library
(ipsec.h), since in this way they can be shared with other applications.

ablkcipher encrypt / decrypt shared descriptors are refactored into
a single descriptor and moved in RTA (algo.h) for the same reason.

Other descriptors (for e.g. from caamhash) are left as is,
since they are not general purpose.

Signed-off-by: Horia Geanta <horia.geanta@xxxxxxxxxxxxx>
---
 drivers/crypto/caam/caamalg.c         | 592 +++++-----------------------------
 drivers/crypto/caam/flib/desc/algo.h  |  88 +++++
 drivers/crypto/caam/flib/desc/ipsec.h | 550 +++++++++++++++++++++++++++++++
 3 files changed, 720 insertions(+), 510 deletions(-)
 create mode 100644 drivers/crypto/caam/flib/desc/algo.h
 create mode 100644 drivers/crypto/caam/flib/desc/ipsec.h

diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index 9090fc8c04e0..746bb0b21695 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -50,6 +50,8 @@
 #include "intern.h"
 #include "flib/rta.h"
 #include "flib/desc/common.h"
+#include "flib/desc/algo.h"
+#include "flib/desc/ipsec.h"
 #include "jr.h"
 #include "error.h"
 #include "sg_sw_sec4.h"
@@ -65,22 +67,7 @@
 /* max IV is max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
 #define CAAM_MAX_IV_LENGTH		16
 
-/* length of descriptors text */
-#define DESC_AEAD_BASE			(4 * CAAM_CMD_SZ)
-#define DESC_AEAD_ENC_LEN		(DESC_AEAD_BASE + 15 * CAAM_CMD_SZ)
-#define DESC_AEAD_DEC_LEN		(DESC_AEAD_BASE + 18 * CAAM_CMD_SZ)
-#define DESC_AEAD_GIVENC_LEN		(DESC_AEAD_ENC_LEN + 7 * CAAM_CMD_SZ)
-
-#define DESC_AEAD_NULL_BASE		(3 * CAAM_CMD_SZ)
-#define DESC_AEAD_NULL_ENC_LEN		(DESC_AEAD_NULL_BASE + 14 * CAAM_CMD_SZ)
-#define DESC_AEAD_NULL_DEC_LEN		(DESC_AEAD_NULL_BASE + 17 * CAAM_CMD_SZ)
-
-#define DESC_ABLKCIPHER_BASE		(3 * CAAM_CMD_SZ)
-#define DESC_ABLKCIPHER_ENC_LEN		(DESC_ABLKCIPHER_BASE + \
-					 20 * CAAM_CMD_SZ)
-#define DESC_ABLKCIPHER_DEC_LEN		(DESC_ABLKCIPHER_BASE + \
-					 15 * CAAM_CMD_SZ)
-
+/* maximum length of descriptors text */
 #define DESC_MAX_USED_BYTES		(DESC_AEAD_GIVENC_LEN + \
 					 CAAM_MAX_KEY_SIZE)
 #define DESC_MAX_USED_LEN		(DESC_MAX_USED_BYTES / CAAM_CMD_SZ)
@@ -124,96 +111,33 @@ struct caam_ctx {
 
 static int aead_null_set_sh_desc(struct crypto_aead *aead)
 {
-	struct aead_tfm *tfm = &aead->base.crt_aead;
 	struct caam_ctx *ctx = crypto_aead_ctx(aead);
 	struct device *jrdev = ctx->jrdev;
-	bool keys_fit_inline = false;
 	u32 *desc;
-	struct program prg;
-	struct program *p = &prg;
 	unsigned desc_bytes;
-	LABEL(skip_key_load);
-	REFERENCE(pskip_key_load);
-	LABEL(nop_cmd);
-	REFERENCE(pnop_cmd);
-	LABEL(read_move_cmd);
-	REFERENCE(pread_move_cmd);
-	LABEL(write_move_cmd);
-	REFERENCE(pwrite_move_cmd);
+	struct alginfo authdata;
+	int rem_bytes = CAAM_DESC_BYTES_MAX - (DESC_JOB_IO_LEN +
+			ctx->split_key_pad_len);
+
+	authdata.algtype = ctx->class2_alg_type;
+	authdata.key_enc_flags = ENC;
+	authdata.keylen = ctx->split_key_len;
 
 	/*
 	 * Job Descriptor and Shared Descriptors
 	 * must all fit into the 64-word Descriptor h/w Buffer
 	 */
-	if (DESC_AEAD_NULL_ENC_LEN + DESC_JOB_IO_LEN +
-	    ctx->split_key_pad_len <= CAAM_DESC_BYTES_MAX)
-		keys_fit_inline = true;
+	if (rem_bytes >= DESC_AEAD_NULL_ENC_LEN) {
+		authdata.key = (uintptr_t)ctx->key;
+		authdata.key_type = RTA_DATA_IMM;
+	} else {
+		authdata.key = ctx->key_dma;
+		authdata.key_type = RTA_DATA_PTR;
+	}
 
 	/* aead_encrypt shared descriptor */
 	desc = ctx->sh_desc_enc;
-	PROGRAM_CNTXT_INIT(p, desc, 0);
-	if (ps)
-		PROGRAM_SET_36BIT_ADDR(p);
-
-	SHR_HDR(p, SHR_SERIAL, 1, 0);
-
-	/* Skip if already shared */
-	pskip_key_load = JUMP(p, skip_key_load, LOCAL_JUMP, ALL_TRUE, SHRD);
-	if (keys_fit_inline)
-		KEY(p, MDHA_SPLIT_KEY, ENC, (uintptr_t)ctx->key,
-		    ctx->split_key_len, IMMED | COPY);
-	else
-		KEY(p, MDHA_SPLIT_KEY, ENC, ctx->key_dma, ctx->split_key_len,
-		    0);
-	SET_LABEL(p, skip_key_load);
-
-	/* cryptlen = seqoutlen - authsize */
-	MATHB(p, SEQOUTSZ, SUB, ctx->authsize, MATH3, CAAM_CMD_SZ, IMMED2);
-
-	/*
-	 * NULL encryption; IV is zero
-	 * assoclen = (assoclen + cryptlen) - cryptlen
-	 */
-	MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, CAAM_CMD_SZ, 0);
-
-	/* read assoc before reading payload */
-	SEQFIFOLOAD(p, MSG2, 0 , VLF);
-
-	/* Prepare to read and write cryptlen bytes */
-	MATHB(p, ZERO, ADD, MATH3, VSEQINSZ, CAAM_CMD_SZ, 0);
-	MATHB(p, ZERO, ADD, MATH3, VSEQOUTSZ, CAAM_CMD_SZ, 0);
-
-	/*
-	 * MOVE_LEN opcode is not available in all SEC HW revisions,
-	 * thus need to do some magic, i.e. self-patch the descriptor
-	 * buffer.
-	 */
-	pread_move_cmd = MOVE(p, DESCBUF, 0, MATH3, 0, 6, IMMED);
-	pwrite_move_cmd = MOVE(p, MATH3, 0, DESCBUF, 0, 8, WAITCOMP | IMMED);
-
-	/* Class 2 operation */
-	ALG_OPERATION(p, ctx->class2_alg_type & OP_ALG_ALGSEL_MASK,
-		      ctx->class2_alg_type & OP_ALG_AAI_MASK,
-		      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
-
-	/* Read and write cryptlen bytes */
-	SEQFIFOSTORE(p, MSG, 0, 0, VLF);
-	SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
-
-	SET_LABEL(p, read_move_cmd);
-	SET_LABEL(p, write_move_cmd);
-	LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
-	MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
-
-	/* Write ICV */
-	SEQSTORE(p, CONTEXT2, 0, ctx->authsize, 0);
-
-	PATCH_JUMP(p, pskip_key_load, skip_key_load);
-	PATCH_MOVE(p, pread_move_cmd, read_move_cmd);
-	PATCH_MOVE(p, pwrite_move_cmd, write_move_cmd);
-
-	PROGRAM_FINALIZE(p);
-
+	cnstr_shdsc_aead_null_encap(desc, ps, &authdata, ctx->authsize);
 	desc_bytes = DESC_BYTES(desc);
 	ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc, desc_bytes,
 					      DMA_TO_DEVICE);
@@ -231,83 +155,17 @@ static int aead_null_set_sh_desc(struct crypto_aead *aead)
 	 * Job Descriptor and Shared Descriptors
 	 * must all fit into the 64-word Descriptor h/w Buffer
 	 */
-	keys_fit_inline = false;
-	if (DESC_AEAD_NULL_DEC_LEN + DESC_JOB_IO_LEN +
-	    ctx->split_key_pad_len <= CAAM_DESC_BYTES_MAX)
-		keys_fit_inline = true;
+	if (rem_bytes >= DESC_AEAD_NULL_DEC_LEN) {
+		authdata.key = (uintptr_t)ctx->key;
+		authdata.key_type = RTA_DATA_IMM;
+	} else {
+		authdata.key = ctx->key_dma;
+		authdata.key_type = RTA_DATA_PTR;
+	}
 
 	/* aead_decrypt shared descriptor */
 	desc = ctx->sh_desc_dec;
-	PROGRAM_CNTXT_INIT(p, desc, 0);
-	if (ps)
-		PROGRAM_SET_36BIT_ADDR(p);
-
-	SHR_HDR(p, SHR_SERIAL, 1, 0);
-
-	/* Skip if already shared */
-	pskip_key_load = JUMP(p, skip_key_load, LOCAL_JUMP, ALL_TRUE, SHRD);
-	if (keys_fit_inline)
-		KEY(p, MDHA_SPLIT_KEY, ENC, (uintptr_t)ctx->key,
-		    ctx->split_key_len, IMMED | COPY);
-	else
-		KEY(p, MDHA_SPLIT_KEY, ENC, ctx->key_dma, ctx->split_key_len,
-		    0);
-	SET_LABEL(p, skip_key_load);
-
-	/* Class 2 operation */
-	ALG_OPERATION(p, ctx->class2_alg_type & OP_ALG_ALGSEL_MASK,
-		      ctx->class2_alg_type & OP_ALG_AAI_MASK,
-		      OP_ALG_AS_INITFINAL, ICV_CHECK_ENABLE, DIR_DEC);
-
-	/* assoclen + cryptlen = seqinlen - ivsize - authsize */
-	MATHB(p, SEQINSZ, SUB, ctx->authsize + tfm->ivsize, MATH3, CAAM_CMD_SZ,
-	      IMMED2);
-	/* assoclen = (assoclen + cryptlen) - cryptlen */
-	MATHB(p, SEQOUTSZ, SUB, MATH0, MATH2, CAAM_CMD_SZ, 0);
-	MATHB(p, MATH3, SUB, MATH2, VSEQINSZ, CAAM_CMD_SZ, 0);
-
-	/* read assoc before reading payload */
-	SEQFIFOLOAD(p, MSG2, 0 , VLF);
-
-	/* Prepare to read and write cryptlen bytes */
-	MATHB(p, ZERO, ADD, MATH2, VSEQINSZ, CAAM_CMD_SZ, 0);
-	MATHB(p, ZERO, ADD, MATH2, VSEQOUTSZ, CAAM_CMD_SZ, 0);
-
-	/*
-	 * MOVE_LEN opcode is not available in all SEC HW revisions,
-	 * thus need to do some magic, i.e. self-patch the descriptor
-	 * buffer.
-	 */
-	pread_move_cmd = MOVE(p, DESCBUF, 0, MATH2, 0, 6, IMMED);
-	pwrite_move_cmd = MOVE(p, MATH2, 0, DESCBUF, 0, 8, WAITCOMP | IMMED);
-
-	/* Read and write cryptlen bytes */
-	SEQFIFOSTORE(p, MSG, 0, 0, VLF);
-	SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
-
-	/*
-	 * Insert a NOP here, since we need at least 4 instructions between
-	 * code patching the descriptor buffer and the location being patched.
-	 */
-	pnop_cmd = JUMP(p, nop_cmd, LOCAL_JUMP, ALL_TRUE, 0);
-	SET_LABEL(p, nop_cmd);
-
-	SET_LABEL(p, read_move_cmd);
-	SET_LABEL(p, write_move_cmd);
-	LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
-	MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
-	LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
-
-	/* Load ICV */
-	SEQFIFOLOAD(p, ICV2, ctx->authsize, LAST2);
-
-	PATCH_JUMP(p, pskip_key_load, skip_key_load);
-	PATCH_JUMP(p, pnop_cmd, nop_cmd);
-	PATCH_MOVE(p, pread_move_cmd, read_move_cmd);
-	PATCH_MOVE(p, pwrite_move_cmd, write_move_cmd);
-
-	PROGRAM_FINALIZE(p);
-
+	cnstr_shdsc_aead_null_decap(desc, ps, &authdata, ctx->authsize);
 	desc_bytes = DESC_BYTES(desc);
 	ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc, desc_bytes,
 					      DMA_TO_DEVICE);
@@ -329,18 +187,10 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
 	struct aead_tfm *tfm = &aead->base.crt_aead;
 	struct caam_ctx *ctx = crypto_aead_ctx(aead);
 	struct device *jrdev = ctx->jrdev;
-	bool keys_fit_inline = false;
-	u32 geniv, moveiv;
 	u32 *desc;
-	struct program prg;
-	struct program *p = &prg;
 	unsigned desc_bytes;
-	LABEL(skip_key_load);
-	REFERENCE(pskip_key_load);
-	LABEL(set_dk);
-	REFERENCE(pset_dk);
-	LABEL(skip_dk);
-	REFERENCE(pskip_dk);
+	struct alginfo cipherdata, authdata;
+	int rem_bytes;
 
 	if (!ctx->authsize)
 		return 0;
@@ -349,81 +199,34 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
 	if (!ctx->enckeylen)
 		return aead_null_set_sh_desc(aead);
 
+	cipherdata.algtype = ctx->class1_alg_type;
+	cipherdata.key_enc_flags = 0;
+	cipherdata.keylen = ctx->enckeylen;
+	authdata.algtype = ctx->class2_alg_type;
+	authdata.key_enc_flags = ENC;
+	authdata.keylen = ctx->split_key_len;
+
+	rem_bytes = CAAM_DESC_BYTES_MAX - (DESC_JOB_IO_LEN +
+		    ctx->split_key_pad_len + ctx->enckeylen);
+
 	/*
 	 * Job Descriptor and Shared Descriptors
 	 * must all fit into the 64-word Descriptor h/w Buffer
 	 */
-	if (DESC_AEAD_ENC_LEN + DESC_JOB_IO_LEN +
-	    ctx->split_key_pad_len + ctx->enckeylen <=
-	    CAAM_DESC_BYTES_MAX)
-		keys_fit_inline = true;
-
-	/* aead_encrypt shared descriptor */
-	desc = ctx->sh_desc_enc;
-	PROGRAM_CNTXT_INIT(p, desc, 0);
-	if (ps)
-		PROGRAM_SET_36BIT_ADDR(p);
-
-	SHR_HDR(p, SHR_SERIAL, 1, 0);
-
-	/* Skip key loading if already shared */
-	pskip_key_load = JUMP(p, skip_key_load, LOCAL_JUMP, ALL_TRUE, SHRD);
-
-	if (keys_fit_inline) {
-		KEY(p, MDHA_SPLIT_KEY, ENC, (uintptr_t)ctx->key,
-		    ctx->split_key_len, IMMED | COPY);
-		KEY(p, KEY1, 0, (uintptr_t)(ctx->key + ctx->split_key_pad_len),
-		    ctx->enckeylen, IMMED | COPY);
+	if (rem_bytes >= DESC_AEAD_ENC_LEN) {
+		authdata.key = (uintptr_t)ctx->key;
+		authdata.key_type = RTA_DATA_IMM;
 	} else {
-		KEY(p, MDHA_SPLIT_KEY, ENC, ctx->key_dma, ctx->split_key_len,
-		    0);
-		KEY(p, KEY1, 0, ctx->key_dma + ctx->split_key_pad_len,
-		    ctx->enckeylen, 0);
+		authdata.key = ctx->key_dma;
+		authdata.key_type = RTA_DATA_PTR;
 	}
+	cipherdata.key = authdata.key + ctx->split_key_pad_len;
+	cipherdata.key_type = authdata.key_type;
 
-	SET_LABEL(p, skip_key_load);
-
-	/* Class 2 operation */
-	ALG_OPERATION(p, ctx->class2_alg_type & OP_ALG_ALGSEL_MASK,
-		      ctx->class2_alg_type & OP_ALG_AAI_MASK,
-		      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
-
-	/* cryptlen = seqoutlen - authsize */
-	MATHB(p, SEQOUTSZ, SUB, ctx->authsize, MATH3, CAAM_CMD_SZ, IMMED2);
-
-	/* assoclen + cryptlen = seqinlen - ivsize */
-	MATHB(p, SEQINSZ, SUB, tfm->ivsize, MATH2, CAAM_CMD_SZ, IMMED2);
-
-	/* assoclen = (assoclen + cryptlen) - cryptlen */
-	MATHB(p, MATH2, SUB, MATH3, VSEQINSZ, CAAM_CMD_SZ, 0);
-
-	/* read assoc before reading payload */
-	SEQFIFOLOAD(p, MSG2, 0 , VLF);
-
-	/* read iv for both classes */
-	SEQLOAD(p, CONTEXT1, 0, tfm->ivsize, 0);
-	MOVE(p, CONTEXT1, 0, IFIFOAB2, 0, tfm->ivsize, IMMED);
-
-	/* Class 1 operation */
-	ALG_OPERATION(p, ctx->class1_alg_type & OP_ALG_ALGSEL_MASK,
-		      ctx->class1_alg_type & OP_ALG_AAI_MASK,
-		      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
-
-	/* Read and write cryptlen bytes */
-	MATHB(p, ZERO, ADD, MATH3, VSEQINSZ, CAAM_CMD_SZ, 0);
-	MATHB(p, ZERO, ADD, MATH3, VSEQOUTSZ, CAAM_CMD_SZ, 0);
-
-	/* Read and write payload */
-	SEQFIFOSTORE(p, MSG, 0, 0, VLF);
-	SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | LAST2);
-
-	/* Write ICV */
-	SEQSTORE(p, CONTEXT2, 0, ctx->authsize, 0);
-
-	PATCH_JUMP(p, pskip_key_load, skip_key_load);
-
-	PROGRAM_FINALIZE(p);
-
+	/* aead_encrypt shared descriptor */
+	desc = ctx->sh_desc_enc;
+	cnstr_shdsc_aead_encap(desc, ps, &cipherdata, &authdata, tfm->ivsize,
+			       ctx->authsize);
 	desc_bytes = DESC_BYTES(desc);
 	ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc, desc_bytes,
 					      DMA_TO_DEVICE);
@@ -440,93 +243,20 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
 	 * Job Descriptor and Shared Descriptors
 	 * must all fit into the 64-word Descriptor h/w Buffer
 	 */
-	keys_fit_inline = false;
-	if (DESC_AEAD_DEC_LEN + DESC_JOB_IO_LEN +
-	    ctx->split_key_pad_len + ctx->enckeylen <=
-	    CAAM_DESC_BYTES_MAX)
-		keys_fit_inline = true;
-
-	/* aead_decrypt shared descriptor */
-	desc = ctx->sh_desc_dec;
-	PROGRAM_CNTXT_INIT(p, desc, 0);
-	if (ps)
-		PROGRAM_SET_36BIT_ADDR(p);
-
-	/* aead_decrypt shared descriptor */
-	SHR_HDR(p, SHR_SERIAL, 1, 0);
-
-	/* Skip key loading if already shared */
-	pskip_key_load = JUMP(p, skip_key_load, LOCAL_JUMP, ALL_TRUE, SHRD);
-
-	if (keys_fit_inline) {
-		KEY(p, MDHA_SPLIT_KEY, ENC, (uintptr_t)ctx->key,
-		    ctx->split_key_len, IMMED | COPY);
-		KEY(p, KEY1, 0, (uintptr_t)(ctx->key + ctx->split_key_pad_len),
-		    ctx->enckeylen, IMMED | COPY);
+	if (rem_bytes >= DESC_AEAD_DEC_LEN) {
+		authdata.key = (uintptr_t)ctx->key;
+		authdata.key_type = RTA_DATA_IMM;
 	} else {
-		KEY(p, MDHA_SPLIT_KEY, ENC, ctx->key_dma, ctx->split_key_len,
-		    0);
-		KEY(p, KEY1, 0, ctx->key_dma + ctx->split_key_pad_len,
-		    ctx->enckeylen, 0);
+		authdata.key = ctx->key_dma;
+		authdata.key_type = RTA_DATA_PTR;
 	}
+	cipherdata.key = authdata.key + ctx->split_key_pad_len;
+	cipherdata.key_type = authdata.key_type;
 
-	SET_LABEL(p, skip_key_load);
-
-	/* Class 2 operation */
-	ALG_OPERATION(p, ctx->class2_alg_type & OP_ALG_ALGSEL_MASK,
-		      ctx->class2_alg_type & OP_ALG_AAI_MASK,
-		      OP_ALG_AS_INITFINAL, ICV_CHECK_ENABLE, DIR_DEC);
-
-	/* assoclen + cryptlen = seqinlen - ivsize - authsize */
-	MATHB(p, SEQINSZ, SUB, ctx->authsize + tfm->ivsize, MATH3, CAAM_CMD_SZ,
-	      IMMED2);
-	/* assoclen = (assoclen + cryptlen) - cryptlen */
-	MATHB(p, SEQOUTSZ, SUB, MATH0, MATH2, CAAM_CMD_SZ, 0);
-	MATHB(p, MATH3, SUB, MATH2, VSEQINSZ, CAAM_CMD_SZ, 0);
-
-	/* read assoc before reading payload */
-	SEQFIFOLOAD(p, MSG2, 0 , VLF);
-
-	/* read iv for both classes */
-	SEQLOAD(p, CONTEXT1, 0, tfm->ivsize, 0);
-	MOVE(p, CONTEXT1, 0, IFIFOAB2, 0, tfm->ivsize, IMMED);
-
-	/* Set DK bit in class 1 operation if shared (AES only) */
-	if ((ctx->class1_alg_type & OP_ALG_ALGSEL_MASK) == OP_ALG_ALGSEL_AES) {
-		pset_dk = JUMP(p, set_dk, LOCAL_JUMP, ALL_TRUE, SHRD);
-		ALG_OPERATION(p, ctx->class1_alg_type & OP_ALG_ALGSEL_MASK,
-			      ctx->class1_alg_type & OP_ALG_AAI_MASK,
-			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_DEC);
-		pskip_dk = JUMP(p, skip_dk, LOCAL_JUMP, ALL_TRUE, 0);
-		SET_LABEL(p, set_dk);
-		ALG_OPERATION(p, ctx->class1_alg_type & OP_ALG_ALGSEL_MASK,
-			      (ctx->class1_alg_type & OP_ALG_AAI_MASK) |
-			       OP_ALG_AAI_DK, OP_ALG_AS_INITFINAL,
-			      ICV_CHECK_DISABLE, DIR_DEC);
-		SET_LABEL(p, skip_dk);
-	} else {
-		ALG_OPERATION(p, ctx->class1_alg_type & OP_ALG_ALGSEL_MASK,
-			      ctx->class1_alg_type & OP_ALG_AAI_MASK,
-			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_DEC);
-	}
-
-	/* Read and write cryptlen bytes */
-	MATHB(p, ZERO, ADD, MATH2, VSEQINSZ, CAAM_CMD_SZ, 0);
-	MATHB(p, ZERO, ADD, MATH2, VSEQOUTSZ, CAAM_CMD_SZ, 0);
-
-	/* Read and write payload */
-	SEQFIFOSTORE(p, MSG, 0, 0, VLF);
-	SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2);
-
-	/* Load ICV */
-	SEQFIFOLOAD(p, ICV2, ctx->authsize, LAST2);
-
-	PATCH_JUMP(p, pskip_key_load, skip_key_load);
-	PATCH_JUMP(p, pset_dk, set_dk);
-	PATCH_JUMP(p, pskip_dk, skip_dk);
-
-	PROGRAM_FINALIZE(p);
-
+	/* aead_decrypt shared descriptor */
+	desc = ctx->sh_desc_dec;
+	cnstr_shdsc_aead_decap(desc, ps, &cipherdata, &authdata, tfm->ivsize,
+			       ctx->authsize);
 	desc_bytes = DESC_BYTES(desc);
 	ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc, desc_bytes,
 					      DMA_TO_DEVICE);
@@ -543,95 +273,20 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
 	 * Job Descriptor and Shared Descriptors
 	 * must all fit into the 64-word Descriptor h/w Buffer
 	 */
-	keys_fit_inline = false;
-	if (DESC_AEAD_GIVENC_LEN + DESC_JOB_IO_LEN +
-	    ctx->split_key_pad_len + ctx->enckeylen <=
-	    CAAM_DESC_BYTES_MAX)
-		keys_fit_inline = true;
-
-	/* aead_givencrypt shared descriptor */
-	desc = ctx->sh_desc_givenc;
-	PROGRAM_CNTXT_INIT(p, desc, 0);
-	if (ps)
-		PROGRAM_SET_36BIT_ADDR(p);
-
-	SHR_HDR(p, SHR_SERIAL, 1, 0);
-
-	/* Skip key loading if already shared */
-	pskip_key_load = JUMP(p, skip_key_load, LOCAL_JUMP, ALL_TRUE, SHRD);
-
-	if (keys_fit_inline) {
-		KEY(p, MDHA_SPLIT_KEY, ENC, (uintptr_t)ctx->key,
-		    ctx->split_key_len, IMMED | COPY);
-		KEY(p, KEY1, 0,
-		    (uintptr_t)(ctx->key + ctx->split_key_pad_len),
-		    ctx->enckeylen, IMMED | COPY);
+	if (rem_bytes >= DESC_AEAD_GIVENC_LEN) {
+		authdata.key = (uintptr_t)ctx->key;
+		authdata.key_type = RTA_DATA_IMM;
 	} else {
-		KEY(p, MDHA_SPLIT_KEY, ENC, ctx->key_dma, ctx->split_key_len,
-		    0);
-		KEY(p, KEY1, 0, ctx->key_dma + ctx->split_key_pad_len,
-		    ctx->enckeylen, 0);
+		authdata.key = ctx->key_dma;
+		authdata.key_type = RTA_DATA_PTR;
 	}
+	cipherdata.key = authdata.key + ctx->split_key_pad_len;
+	cipherdata.key_type = authdata.key_type;
 
-	SET_LABEL(p, skip_key_load);
-
-	/* Generate IV */
-	geniv = NFIFOENTRY_STYPE_PAD | NFIFOENTRY_DEST_DECO |
-		NFIFOENTRY_DTYPE_MSG | NFIFOENTRY_LC1 |
-		NFIFOENTRY_PTYPE_RND | (tfm->ivsize << NFIFOENTRY_DLEN_SHIFT);
-	LOAD(p, geniv, NFIFO, 0, CAAM_CMD_SZ, IMMED);
-	LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
-	MOVE(p, IFIFOABD, 0, CONTEXT1, 0, tfm->ivsize, IMMED);
-	LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
-
-	/* Copy IV to class 1 context */
-	MOVE(p, CONTEXT1, 0, OFIFO, 0, tfm->ivsize, IMMED);
-
-	/* Return to encryption */
-	ALG_OPERATION(p, ctx->class2_alg_type & OP_ALG_ALGSEL_MASK,
-		      ctx->class2_alg_type & OP_ALG_AAI_MASK,
-		      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
-
-	/* ivsize + cryptlen = seqoutlen - authsize */
-	MATHB(p, SEQOUTSZ, SUB, ctx->authsize, MATH3, CAAM_CMD_SZ, IMMED2);
-
-	/* assoclen = seqinlen - (ivsize + cryptlen) */
-	MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, CAAM_CMD_SZ, 0);
-
-	/* read assoc before reading payload */
-	SEQFIFOLOAD(p, MSG2, 0, VLF);
-
-	/* Copy iv from class 1 ctx to class 2 fifo*/
-	moveiv = NFIFOENTRY_STYPE_OFIFO | NFIFOENTRY_DEST_CLASS2 |
-		 NFIFOENTRY_DTYPE_MSG | (tfm->ivsize << NFIFOENTRY_DLEN_SHIFT);
-	LOAD(p, moveiv, NFIFO, 0, CAAM_CMD_SZ, IMMED);
-	LOAD(p, tfm->ivsize, DATA2SZ, 0, CAAM_CMD_SZ, IMMED);
-
-	/* Class 1 operation */
-	ALG_OPERATION(p, ctx->class1_alg_type & OP_ALG_ALGSEL_MASK,
-		      ctx->class1_alg_type & OP_ALG_AAI_MASK,
-		      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
-
-	/* Will write ivsize + cryptlen */
-	MATHB(p, SEQINSZ, ADD, MATH0, VSEQOUTSZ, CAAM_CMD_SZ, 0);
-
-	/* Not need to reload iv */
-	SEQFIFOLOAD(p, SKIP, tfm->ivsize, 0);
-
-	/* Will read cryptlen */
-	MATHB(p, SEQINSZ, ADD, MATH0, VSEQINSZ, CAAM_CMD_SZ, 0);
-
-	/* Read and write payload */
-	SEQFIFOSTORE(p, MSG, 0, 0, VLF);
-	SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | LAST2);
-
-	/* Write ICV */
-	SEQSTORE(p, CONTEXT2, 0, ctx->authsize, 0);
-
-	PATCH_JUMP(p, pskip_key_load, skip_key_load);
-
-	PROGRAM_FINALIZE(p);
-
+	/* aead_givencrypt shared descriptor */
+	desc = ctx->sh_desc_givenc;
+	cnstr_shdsc_aead_givencap(desc, ps, &cipherdata, &authdata, tfm->ivsize,
+				  ctx->authsize);
 	desc_bytes = DESC_BYTES(desc);
 	ctx->sh_desc_givenc_dma = dma_map_single(jrdev, desc, desc_bytes,
 						 DMA_TO_DEVICE);
@@ -737,15 +392,8 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
 	struct device *jrdev = ctx->jrdev;
 	int ret = 0;
 	u32 *desc;
-	struct program prg;
-	struct program *p = &prg;
 	unsigned desc_bytes;
-	LABEL(skip_key_load);
-	REFERENCE(pskip_key_load);
-	LABEL(set_dk);
-	REFERENCE(pset_dk);
-	LABEL(skip_dk);
-	REFERENCE(pskip_dk);
+	struct alginfo cipherdata;
 
 #ifdef DEBUG
 	print_hex_dump(KERN_ERR, "key in @"__stringify(__LINE__)": ",
@@ -753,48 +401,18 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
 #endif
 
 	memcpy(ctx->key, key, keylen);
-	ctx->key_dma = dma_map_single(jrdev, ctx->key, keylen,
-				      DMA_TO_DEVICE);
-	if (dma_mapping_error(jrdev, ctx->key_dma)) {
-		dev_err(jrdev, "unable to map key i/o memory\n");
-		return -ENOMEM;
-	}
 	ctx->enckeylen = keylen;
 
+	cipherdata.algtype = ctx->class1_alg_type & OP_ALG_ALGSEL_MASK;
+	cipherdata.key_enc_flags = 0;
+	cipherdata.keylen = ctx->enckeylen;
+	cipherdata.key = (uintptr_t)ctx->key;
+	cipherdata.key_type = RTA_DATA_IMM;
+
 	/* ablkcipher_encrypt shared descriptor */
 	desc = ctx->sh_desc_enc;
-	PROGRAM_CNTXT_INIT(p, desc, 0);
-	if (ps)
-		PROGRAM_SET_36BIT_ADDR(p);
-
-	SHR_HDR(p, SHR_SERIAL, 1, 0);
-
-	/* Skip key loading if already shared */
-	pskip_key_load = JUMP(p, skip_key_load, LOCAL_JUMP, ALL_TRUE, SHRD);
-
-	/* Load class1 key only */
-	KEY(p, KEY1, 0, (uintptr_t)ctx->key, ctx->enckeylen, IMMED | COPY);
-
-	SET_LABEL(p, skip_key_load);
-
-	/* Load IV */
-	SEQLOAD(p, CONTEXT1, 0, tfm->ivsize, 0);
-
-	/* Load operation */
-	ALG_OPERATION(p, ctx->class1_alg_type & OP_ALG_ALGSEL_MASK,
-		      ctx->class1_alg_type & OP_ALG_AAI_MASK,
-		      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
-
-	/* Perform operation */
-	MATHB(p, SEQINSZ, ADD, MATH0, VSEQOUTSZ, 4, 0);
-	MATHB(p, SEQINSZ, ADD, MATH0, VSEQINSZ, 4, 0);
-	SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1);
-	SEQFIFOSTORE(p, MSG, 0, 0, VLF);
-
-	PATCH_JUMP(p, pskip_key_load, skip_key_load);
-
-	PROGRAM_FINALIZE(p);
-
+	cnstr_shdsc_cbc_blkcipher(desc, ps, &cipherdata, NULL, tfm->ivsize,
+				  DIR_ENC);
 	desc_bytes = DESC_BYTES(desc);
 	ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc, desc_bytes,
 					      DMA_TO_DEVICE);
@@ -810,54 +428,8 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
 
 	/* ablkcipher_decrypt shared descriptor */
 	desc = ctx->sh_desc_dec;
-	PROGRAM_CNTXT_INIT(p, desc, 0);
-	if (ps)
-		PROGRAM_SET_36BIT_ADDR(p);
-
-	SHR_HDR(p, SHR_SERIAL, 1, 0);
-
-	/* Skip key loading if already shared */
-	pskip_key_load = JUMP(p, skip_key_load, LOCAL_JUMP, ALL_TRUE, SHRD);
-
-	/* Load class1 key only */
-	KEY(p, KEY1, 0, (uintptr_t)ctx->key, ctx->enckeylen, IMMED | COPY);
-
-	SET_LABEL(p, skip_key_load);
-
-	/* load IV */
-	SEQLOAD(p, CONTEXT1, 0, tfm->ivsize, 0);
-
-	/* Set DK bit in class 1 operation if shared (AES only) */
-	if ((ctx->class1_alg_type & OP_ALG_ALGSEL_MASK) == OP_ALG_ALGSEL_AES) {
-		pset_dk = JUMP(p, set_dk, LOCAL_JUMP, ALL_TRUE, SHRD);
-		ALG_OPERATION(p, ctx->class1_alg_type & OP_ALG_ALGSEL_MASK,
-			      ctx->class1_alg_type & OP_ALG_AAI_MASK,
-			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_DEC);
-		pskip_dk = JUMP(p, skip_dk, LOCAL_JUMP, ALL_TRUE, 0);
-		SET_LABEL(p, set_dk);
-		ALG_OPERATION(p, ctx->class1_alg_type & OP_ALG_ALGSEL_MASK,
-			      (ctx->class1_alg_type & OP_ALG_AAI_MASK) |
-			       OP_ALG_AAI_DK, OP_ALG_AS_INITFINAL,
-			      ICV_CHECK_DISABLE, DIR_DEC);
-		SET_LABEL(p, skip_dk);
-	} else {
-		ALG_OPERATION(p, ctx->class1_alg_type & OP_ALG_ALGSEL_MASK,
-			      ctx->class1_alg_type & OP_ALG_AAI_MASK,
-			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_DEC);
-	}
-
-	/* Perform operation */
-	MATHB(p, SEQINSZ, ADD, MATH0, VSEQOUTSZ, 4, 0);
-	MATHB(p, SEQINSZ, ADD, MATH0, VSEQINSZ, 4, 0);
-	SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1);
-	SEQFIFOSTORE(p, MSG, 0, 0, VLF);
-
-	PATCH_JUMP(p, pskip_key_load, skip_key_load);
-	PATCH_JUMP(p, pset_dk, set_dk);
-	PATCH_JUMP(p, pskip_dk, skip_dk);
-
-	PROGRAM_FINALIZE(p);
-
+	cnstr_shdsc_cbc_blkcipher(desc, ps, &cipherdata, NULL, tfm->ivsize,
+				  DIR_DEC);
 	desc_bytes = DESC_BYTES(desc);
 	ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc, desc_bytes,
 					      DMA_TO_DEVICE);
diff --git a/drivers/crypto/caam/flib/desc/algo.h b/drivers/crypto/caam/flib/desc/algo.h
new file mode 100644
index 000000000000..652d7f55f5e6
--- /dev/null
+++ b/drivers/crypto/caam/flib/desc/algo.h
@@ -0,0 +1,88 @@
+/* Copyright 2008-2013 Freescale Semiconductor, Inc. */
+
+#ifndef __DESC_ALGO_H__
+#define __DESC_ALGO_H__
+
+#include "flib/rta.h"
+#include "common.h"
+
+/**
+ * DOC: Algorithms - Shared Descriptor Constructors
+ *
+ * Shared descriptors for algorithms (i.e. not for protocols).
+ */
+
+/**
+ * cnstr_shdsc_cbc_blkcipher - CBC block cipher
+ * @descbuf: pointer to descriptor-under-construction buffer
+ * @ps: if 36/40bit addressing is desired, this parameter must be true
+ * @cipherdata: pointer to block cipher transform definitions
+ * @iv: IV data; if NULL, "ivlen" bytes from the input frame will be read as IV
+ * @ivlen: IV length
+ * @dir: DIR_ENCRYPT/DIR_DECRYPT
+ *
+ * Return: size of descriptor written in words
+ */
+static inline int cnstr_shdsc_cbc_blkcipher(uint32_t *descbuf, bool ps,
+			       struct alginfo *cipherdata, uint8_t *iv,
+			       uint32_t ivlen, uint8_t dir)
+{
+	struct program prg;
+	struct program *p = &prg;
+	const bool is_aes_dec = (dir == DIR_DEC) &&
+				(cipherdata->algtype == OP_ALG_ALGSEL_AES);
+	LABEL(keyjmp);
+	LABEL(skipdk);
+	REFERENCE(pkeyjmp);
+	REFERENCE(pskipdk);
+
+	PROGRAM_CNTXT_INIT(p, descbuf, 0);
+	if (ps)
+		PROGRAM_SET_36BIT_ADDR(p);
+	SHR_HDR(p, SHR_SERIAL, 1, SC);
+
+	pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
+	/* Insert Key */
+	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
+	    cipherdata->keylen, INLINE_KEY(cipherdata));
+
+	if (is_aes_dec) {
+		ALG_OPERATION(p, cipherdata->algtype, OP_ALG_AAI_CBC,
+			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir);
+
+		pskipdk = JUMP(p, skipdk, LOCAL_JUMP, ALL_TRUE, 0);
+	}
+	SET_LABEL(p, keyjmp);
+
+	if (is_aes_dec) {
+		ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CBC |
+			      OP_ALG_AAI_DK, OP_ALG_AS_INITFINAL,
+			      ICV_CHECK_DISABLE, dir);
+		SET_LABEL(p, skipdk);
+	} else {
+		ALG_OPERATION(p, cipherdata->algtype, OP_ALG_AAI_CBC,
+			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir);
+	}
+
+	if (iv)
+		/* IV load, convert size */
+		LOAD(p, (uintptr_t)iv, CONTEXT1, 0, ivlen, IMMED | COPY);
+	else
+		/* IV is present first before the actual message */
+		SEQLOAD(p, CONTEXT1, 0, ivlen, 0);
+
+	MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
+	MATHB(p, SEQINSZ, SUB, MATH2, VSEQOUTSZ, 4, 0);
+
+	/* Insert sequence load/store with VLF */
+	SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1);
+	SEQFIFOSTORE(p, MSG, 0, 0, VLF);
+
+	PATCH_JUMP(p, pkeyjmp, keyjmp);
+	if (is_aes_dec)
+		PATCH_JUMP(p, pskipdk, skipdk);
+
+	return PROGRAM_FINALIZE(p);
+}
+
+#endif /* __DESC_ALGO_H__ */
diff --git a/drivers/crypto/caam/flib/desc/ipsec.h b/drivers/crypto/caam/flib/desc/ipsec.h
new file mode 100644
index 000000000000..b5436133d26c
--- /dev/null
+++ b/drivers/crypto/caam/flib/desc/ipsec.h
@@ -0,0 +1,550 @@
+/* Copyright 2008-2013 Freescale Semiconductor, Inc. */
+
+#ifndef __DESC_IPSEC_H__
+#define __DESC_IPSEC_H__
+
+#include "flib/rta.h"
+#include "common.h"
+
+/**
+ * DOC: IPsec Shared Descriptor Constructors
+ *
+ * Shared descriptors for IPsec protocol.
+ */
+
+#define DESC_AEAD_BASE		(4 * CAAM_CMD_SZ)
+
+/**
+ * DESC_AEAD_ENC_LEN - Length of descriptor built by cnstr_shdsc_aead_encap().
+ *
+ * Does not account for the key lengths. It is intended to be used by upper
+ * layers to determine whether keys can be inlined or not.
+ */
+#define DESC_AEAD_ENC_LEN	(DESC_AEAD_BASE + 15 * CAAM_CMD_SZ)
+
+/**
+ * cnstr_shdsc_aead_encap - IPSec ESP encapsulation shared descriptor
+ *                          (non-protocol).
+ * @descbuf: pointer to buffer used for descriptor construction
+ * @ps: if 36/40bit addressing is desired, this parameter must be true
+ * @cipherdata: pointer to block cipher transform definitions
+ *              Valid algorithm values - one of OP_ALG_ALGSEL_{AES, DES, 3DES}
+ *              ANDed with OP_ALG_AAI_CBC.
+ * @authdata: pointer to authentication transform definitions. Note that since a
+ *            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)
+ *
+ * Note: Requires an MDHA split key.
+ *
+ * Return: size of descriptor written in words
+ */
+static inline int cnstr_shdsc_aead_encap(uint32_t *descbuf, bool ps,
+					 struct alginfo *cipherdata,
+					 struct alginfo *authdata,
+					 unsigned int ivsize,
+					 unsigned int icvsize)
+{
+	struct program prg;
+	struct program *p = &prg;
+
+	LABEL(skip_key_load);
+	REFERENCE(pskip_key_load);
+
+	PROGRAM_CNTXT_INIT(p, descbuf, 0);
+	if (ps)
+		PROGRAM_SET_36BIT_ADDR(p);
+
+	SHR_HDR(p, SHR_SERIAL, 1, 0);
+
+	/* Skip key loading if already shared */
+	pskip_key_load = JUMP(p, skip_key_load, LOCAL_JUMP, ALL_TRUE, SHRD);
+	KEY(p, MDHA_SPLIT_KEY, authdata->key_enc_flags, authdata->key,
+	    authdata->keylen, INLINE_KEY(authdata));
+	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
+	    cipherdata->keylen, INLINE_KEY(cipherdata));
+	SET_LABEL(p, skip_key_load);
+
+	/* Class 2 operation */
+	ALG_OPERATION(p, authdata->algtype & OP_ALG_ALGSEL_MASK,
+		      authdata->algtype & OP_ALG_AAI_MASK, OP_ALG_AS_INITFINAL,
+		      ICV_CHECK_DISABLE, DIR_ENC);
+
+	/* cryptlen = seqoutlen - authsize */
+	MATHB(p, SEQOUTSZ, SUB, icvsize, MATH3, CAAM_CMD_SZ, IMMED2);
+
+	/* assoclen + cryptlen = seqinlen - ivsize */
+	MATHB(p, SEQINSZ, SUB, ivsize, MATH2, CAAM_CMD_SZ, IMMED2);
+
+	/* assoclen = (assoclen + cryptlen) - cryptlen */
+	MATHB(p, MATH2, SUB, MATH3, VSEQINSZ, CAAM_CMD_SZ, 0);
+
+	/* read assoc before reading payload */
+	SEQFIFOLOAD(p, MSG2, 0 , VLF);
+
+	/* read iv for both classes */
+	SEQLOAD(p, CONTEXT1, 0, ivsize, 0);
+	MOVE(p, CONTEXT1, 0, IFIFOAB2, 0, ivsize, IMMED);
+
+	/* Class 1 operation */
+	ALG_OPERATION(p, cipherdata->algtype & OP_ALG_ALGSEL_MASK,
+		      cipherdata->algtype & OP_ALG_AAI_MASK,
+		      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
+
+	/* Read and write cryptlen bytes */
+	MATHB(p, ZERO, ADD, MATH3, VSEQINSZ, CAAM_CMD_SZ, 0);
+	MATHB(p, ZERO, ADD, MATH3, VSEQOUTSZ, CAAM_CMD_SZ, 0);
+
+	/* Read and write payload */
+	SEQFIFOSTORE(p, MSG, 0, 0, VLF);
+	SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | LAST2);
+
+	/* Write ICV */
+	SEQSTORE(p, CONTEXT2, 0, icvsize, 0);
+
+	PATCH_JUMP(p, pskip_key_load, skip_key_load);
+
+	return PROGRAM_FINALIZE(p);
+}
+
+/**
+ * DESC_AEAD_GIVENC_LEN - Length of descriptor built by
+ *                        cnstr_shdsc_aead_givencap().
+ *
+ * Does not account for the key lengths. It is intended to be used by upper
+ * layers to determine whether keys can be inlined or not.
+ */
+#define DESC_AEAD_GIVENC_LEN	(DESC_AEAD_ENC_LEN + 7 * CAAM_CMD_SZ)
+
+/**
+ * cnstr_shdsc_aead_givencap - IPSec ESP encapsulation shared descriptor
+ *                             (non-protocol) with HW-generated initialization
+ *                             vector.
+ * @descbuf: pointer to buffer used for descriptor construction
+ * @ps: if 36/40bit addressing is desired, this parameter must be true
+ * @cipherdata: pointer to block cipher transform definitions
+ *              Valid algorithm values - one of OP_ALG_ALGSEL_{AES, DES, 3DES}
+ *              ANDed with OP_ALG_AAI_CBC.
+ * @authdata: pointer to authentication transform definitions. Note that since a
+ *            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)
+ *
+ * Note: Requires an MDHA split key.
+ *
+ * Return: size of descriptor written in words
+ */
+static inline int cnstr_shdsc_aead_givencap(uint32_t *descbuf, bool ps,
+					    struct alginfo *cipherdata,
+					    struct alginfo *authdata,
+					    unsigned int ivsize,
+					    unsigned int icvsize)
+{
+	struct program prg;
+	struct program *p = &prg;
+	uint32_t geniv, moveiv;
+
+	LABEL(skip_key_load);
+	REFERENCE(pskip_key_load);
+
+	PROGRAM_CNTXT_INIT(p, descbuf, 0);
+	if (ps)
+		PROGRAM_SET_36BIT_ADDR(p);
+
+	SHR_HDR(p, SHR_SERIAL, 1, 0);
+
+	/* Skip key loading if already shared */
+	pskip_key_load = JUMP(p, skip_key_load, LOCAL_JUMP, ALL_TRUE, SHRD);
+	KEY(p, MDHA_SPLIT_KEY, authdata->key_enc_flags, authdata->key,
+	    authdata->keylen, INLINE_KEY(authdata));
+	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
+	    cipherdata->keylen, INLINE_KEY(cipherdata));
+	SET_LABEL(p, skip_key_load);
+
+	/* Generate IV */
+	geniv = NFIFOENTRY_STYPE_PAD | NFIFOENTRY_DEST_DECO |
+		NFIFOENTRY_DTYPE_MSG | NFIFOENTRY_LC1 |
+		NFIFOENTRY_PTYPE_RND | (ivsize << NFIFOENTRY_DLEN_SHIFT);
+	LOAD(p, geniv, NFIFO, 0, CAAM_CMD_SZ, IMMED);
+	LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
+	MOVE(p, IFIFOABD, 0, CONTEXT1, 0, ivsize, IMMED);
+	LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
+
+	/* Copy IV to class 1 context */
+	MOVE(p, CONTEXT1, 0, OFIFO, 0, ivsize, IMMED);
+
+	/* Return to encryption */
+	ALG_OPERATION(p, authdata->algtype & OP_ALG_ALGSEL_MASK,
+		      authdata->algtype & OP_ALG_AAI_MASK, OP_ALG_AS_INITFINAL,
+		      ICV_CHECK_DISABLE, DIR_ENC);
+
+	/* ivsize + cryptlen = seqoutlen - authsize */
+	MATHB(p, SEQOUTSZ, SUB, icvsize, MATH3, CAAM_CMD_SZ, IMMED2);
+
+	/* assoclen = seqinlen - (ivsize + cryptlen) */
+	MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, CAAM_CMD_SZ, 0);
+
+	/* read assoc before reading payload */
+	SEQFIFOLOAD(p, MSG2, 0, VLF);
+
+	/* Copy iv from class 1 ctx to class 2 fifo*/
+	moveiv = NFIFOENTRY_STYPE_OFIFO | NFIFOENTRY_DEST_CLASS2 |
+		 NFIFOENTRY_DTYPE_MSG | (ivsize << NFIFOENTRY_DLEN_SHIFT);
+	LOAD(p, moveiv, NFIFO, 0, CAAM_CMD_SZ, IMMED);
+	LOAD(p, ivsize, DATA2SZ, 0, CAAM_CMD_SZ, IMMED);
+
+	/* Class 1 operation */
+	ALG_OPERATION(p, cipherdata->algtype & OP_ALG_ALGSEL_MASK,
+		      cipherdata->algtype & OP_ALG_AAI_MASK,
+		      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
+
+	/* Will write ivsize + cryptlen */
+	MATHB(p, SEQINSZ, ADD, MATH0, VSEQOUTSZ, CAAM_CMD_SZ, 0);
+
+	/* Not need to reload iv */
+	SEQFIFOLOAD(p, SKIP, ivsize, 0);
+
+	/* Will read cryptlen */
+	MATHB(p, SEQINSZ, ADD, MATH0, VSEQINSZ, CAAM_CMD_SZ, 0);
+
+	/* Read and write payload */
+	SEQFIFOSTORE(p, MSG, 0, 0, VLF);
+	SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | LAST2);
+
+	/* Write ICV */
+	SEQSTORE(p, CONTEXT2, 0, icvsize, 0);
+
+	PATCH_JUMP(p, pskip_key_load, skip_key_load);
+
+	return PROGRAM_FINALIZE(p);
+}
+
+/**
+ * DESC_AEAD_DEC_LEN - Length of descriptor built by cnstr_shdsc_aead_decap().
+ *
+ * Does not account for the key lengths. It is intended to be used by upper
+ * layers to determine whether keys can be inlined or not.
+ */
+#define DESC_AEAD_DEC_LEN	(DESC_AEAD_BASE + 18 * CAAM_CMD_SZ)
+
+/**
+ * cnstr_shdsc_aead_decap - IPSec ESP decapsulation shared descriptor
+ *                          (non-protocol).
+ * @descbuf: pointer to buffer used for descriptor construction
+ * @ps: if 36/40bit addressing is desired, this parameter must be true
+ * @cipherdata: pointer to block cipher transform definitions
+ *              Valid algorithm values - one of OP_ALG_ALGSEL_{AES, DES, 3DES}
+ *              ANDed with OP_ALG_AAI_CBC.
+ * @authdata: pointer to authentication transform definitions. Note that since a
+ *            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)
+ *
+ * Note: Requires an MDHA split key.
+ *
+ * Return: size of descriptor written in words
+ */
+static inline int cnstr_shdsc_aead_decap(uint32_t *descbuf, bool ps,
+					 struct alginfo *cipherdata,
+					 struct alginfo *authdata,
+					 unsigned int ivsize,
+					 unsigned int icvsize)
+{
+	struct program prg;
+	struct program *p = &prg;
+
+	LABEL(skip_key_load);
+	REFERENCE(pskip_key_load);
+	LABEL(set_dk);
+	REFERENCE(pset_dk);
+	LABEL(skip_dk);
+	REFERENCE(pskip_dk);
+
+	PROGRAM_CNTXT_INIT(p, descbuf, 0);
+	if (ps)
+		PROGRAM_SET_36BIT_ADDR(p);
+
+	/* aead_decrypt shared descriptor */
+	SHR_HDR(p, SHR_SERIAL, 1, 0);
+
+	/* Skip key loading if already shared */
+	pskip_key_load = JUMP(p, skip_key_load, LOCAL_JUMP, ALL_TRUE, SHRD);
+	KEY(p, MDHA_SPLIT_KEY, authdata->key_enc_flags, authdata->key,
+	    authdata->keylen, INLINE_KEY(authdata));
+	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
+	    cipherdata->keylen, INLINE_KEY(cipherdata));
+	SET_LABEL(p, skip_key_load);
+
+	/* Class 2 operation */
+	ALG_OPERATION(p, authdata->algtype & OP_ALG_ALGSEL_MASK,
+		      authdata->algtype & OP_ALG_AAI_MASK, OP_ALG_AS_INITFINAL,
+		      ICV_CHECK_ENABLE, DIR_DEC);
+
+	/* assoclen + cryptlen = seqinlen - ivsize - authsize */
+	MATHB(p, SEQINSZ, SUB, icvsize + ivsize, MATH3, CAAM_CMD_SZ, IMMED2);
+	/* assoclen = (assoclen + cryptlen) - cryptlen */
+	MATHB(p, SEQOUTSZ, SUB, MATH0, MATH2, CAAM_CMD_SZ, 0);
+	MATHB(p, MATH3, SUB, MATH2, VSEQINSZ, CAAM_CMD_SZ, 0);
+
+	/* read assoc before reading payload */
+	SEQFIFOLOAD(p, MSG2, 0 , VLF);
+
+	/* read iv for both classes */
+	SEQLOAD(p, CONTEXT1, 0, ivsize, 0);
+	MOVE(p, CONTEXT1, 0, IFIFOAB2, 0, ivsize, IMMED);
+
+	/* Set DK bit in class 1 operation if shared (AES only) */
+	if ((cipherdata->algtype & OP_ALG_ALGSEL_MASK) == OP_ALG_ALGSEL_AES) {
+		pset_dk = JUMP(p, set_dk, LOCAL_JUMP, ALL_TRUE, SHRD);
+		ALG_OPERATION(p, cipherdata->algtype & OP_ALG_ALGSEL_MASK,
+			      cipherdata->algtype & OP_ALG_AAI_MASK,
+			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
+			      DIR_DEC);
+		pskip_dk = JUMP(p, skip_dk, LOCAL_JUMP, ALL_TRUE, 0);
+		SET_LABEL(p, set_dk);
+		ALG_OPERATION(p, cipherdata->algtype & OP_ALG_ALGSEL_MASK,
+			      (cipherdata->algtype & OP_ALG_AAI_MASK) |
+			       OP_ALG_AAI_DK, OP_ALG_AS_INITFINAL,
+			      ICV_CHECK_DISABLE, DIR_DEC);
+		SET_LABEL(p, skip_dk);
+	} else {
+		ALG_OPERATION(p, cipherdata->algtype & OP_ALG_ALGSEL_MASK,
+			      cipherdata->algtype & OP_ALG_AAI_MASK,
+			      OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
+			      DIR_DEC);
+	}
+
+	/* Read and write cryptlen bytes */
+	MATHB(p, ZERO, ADD, MATH2, VSEQINSZ, CAAM_CMD_SZ, 0);
+	MATHB(p, ZERO, ADD, MATH2, VSEQOUTSZ, CAAM_CMD_SZ, 0);
+
+	/* Read and write payload */
+	SEQFIFOSTORE(p, MSG, 0, 0, VLF);
+	SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2);
+
+	/* Load ICV */
+	SEQFIFOLOAD(p, ICV2, icvsize, LAST2);
+
+	PATCH_JUMP(p, pskip_key_load, skip_key_load);
+	PATCH_JUMP(p, pset_dk, set_dk);
+	PATCH_JUMP(p, pskip_dk, skip_dk);
+
+	return PROGRAM_FINALIZE(p);
+}
+
+#define DESC_AEAD_NULL_BASE		(3 * CAAM_CMD_SZ)
+
+/**
+ * DESC_AEAD_NULL_ENC_LEN - Length of descriptor built by
+ *                          cnstr_shdsc_aead_null_encap().
+ *
+ * Does not account for the key lengths. It is intended to be used by upper
+ * layers to determine whether keys can be inlined or not.
+ */
+#define DESC_AEAD_NULL_ENC_LEN	(DESC_AEAD_NULL_BASE + 14 * CAAM_CMD_SZ)
+
+/**
+ * cnstr_shdsc_aead_null_encap - IPSec ESP encapsulation shared descriptor
+ *                               (non-protocol) with no (null) encryption.
+ * @descbuf: pointer to buffer used for descriptor construction
+ * @ps: if 36/40bit addressing is desired, this parameter must be true
+ * @authdata: pointer to authentication transform definitions. Note that since a
+ *            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.
+ * @icvsize: integrity check value (ICV) size (truncated or full)
+ *
+ * Note: Requires an MDHA split key.
+ *
+ * Return: size of descriptor written in words
+ */
+static inline int cnstr_shdsc_aead_null_encap(uint32_t *descbuf, bool ps,
+					      struct alginfo *authdata,
+					      unsigned int icvsize)
+{
+	struct program prg;
+	struct program *p = &prg;
+
+	LABEL(skip_key_load);
+	REFERENCE(pskip_key_load);
+	LABEL(read_move_cmd);
+	REFERENCE(pread_move_cmd);
+	LABEL(write_move_cmd);
+	REFERENCE(pwrite_move_cmd);
+
+	PROGRAM_CNTXT_INIT(p, descbuf, 0);
+	if (ps)
+		PROGRAM_SET_36BIT_ADDR(p);
+
+	SHR_HDR(p, SHR_SERIAL, 1, 0);
+
+	/* Skip if already shared */
+	pskip_key_load = JUMP(p, skip_key_load, LOCAL_JUMP, ALL_TRUE, SHRD);
+	KEY(p, MDHA_SPLIT_KEY, authdata->key_enc_flags, authdata->key,
+	    authdata->keylen, INLINE_KEY(authdata));
+	SET_LABEL(p, skip_key_load);
+
+	/* cryptlen = seqoutlen - authsize */
+	MATHB(p, SEQOUTSZ, SUB, icvsize, MATH3, CAAM_CMD_SZ, IMMED2);
+
+	/*
+	 * NULL encryption; IV is zero
+	 * assoclen = (assoclen + cryptlen) - cryptlen
+	 */
+	MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, CAAM_CMD_SZ, 0);
+
+	/* read assoc before reading payload */
+	SEQFIFOLOAD(p, MSG2, 0 , VLF);
+
+	/* Prepare to read and write cryptlen bytes */
+	MATHB(p, ZERO, ADD, MATH3, VSEQINSZ, CAAM_CMD_SZ, 0);
+	MATHB(p, ZERO, ADD, MATH3, VSEQOUTSZ, CAAM_CMD_SZ, 0);
+
+	/*
+	 * MOVE_LEN opcode is not available in all SEC HW revisions,
+	 * thus need to do some magic, i.e. self-patch the descriptor buffer.
+	 */
+	pread_move_cmd = MOVE(p, DESCBUF, 0, MATH3, 0, 6, IMMED);
+	pwrite_move_cmd = MOVE(p, MATH3, 0, DESCBUF, 0, 8, WAITCOMP | IMMED);
+
+	/* Class 2 operation */
+	ALG_OPERATION(p, authdata->algtype & OP_ALG_ALGSEL_MASK,
+		      authdata->algtype & OP_ALG_AAI_MASK, OP_ALG_AS_INITFINAL,
+		      ICV_CHECK_DISABLE, DIR_ENC);
+
+	/* Read and write cryptlen bytes */
+	SEQFIFOSTORE(p, MSG, 0, 0, VLF);
+	SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
+
+	SET_LABEL(p, read_move_cmd);
+	SET_LABEL(p, write_move_cmd);
+	LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
+	MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
+
+	/* Write ICV */
+	SEQSTORE(p, CONTEXT2, 0, icvsize, 0);
+
+	PATCH_JUMP(p, pskip_key_load, skip_key_load);
+	PATCH_MOVE(p, pread_move_cmd, read_move_cmd);
+	PATCH_MOVE(p, pwrite_move_cmd, write_move_cmd);
+
+	return PROGRAM_FINALIZE(p);
+}
+
+/**
+ * DESC_AEAD_NULL_DEC_LEN - Length of descriptor built by
+ *                          cnstr_shdsc_aead_null_decap().
+ *
+ * Does not account for the key lengths. It is intended to be used by upper
+ * layers to determine whether keys can be inlined or not.
+ */
+#define DESC_AEAD_NULL_DEC_LEN	(DESC_AEAD_NULL_BASE + 17 * CAAM_CMD_SZ)
+
+/**
+ * cnstr_shdsc_aead_null_decap - IPSec ESP decapsulation shared descriptor
+ *                               (non-protocol) with no (null) decryption.
+ * @descbuf: pointer to buffer used for descriptor construction
+ * @ps: if 36/40bit addressing is desired, this parameter must be true
+ * @authdata: pointer to authentication transform definitions. Note that since a
+ *            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.
+ * @icvsize: integrity check value (ICV) size (truncated or full)
+ *
+ * Note: Requires an MDHA split key.
+ *
+ * Return: size of descriptor written in words
+ */
+static inline int cnstr_shdsc_aead_null_decap(uint32_t *descbuf, bool ps,
+					      struct alginfo *authdata,
+					      unsigned int icvsize)
+{
+	struct program prg;
+	struct program *p = &prg;
+
+	LABEL(skip_key_load);
+	REFERENCE(pskip_key_load);
+	LABEL(nop_cmd);
+	REFERENCE(pnop_cmd);
+	LABEL(read_move_cmd);
+	REFERENCE(pread_move_cmd);
+	LABEL(write_move_cmd);
+	REFERENCE(pwrite_move_cmd);
+
+	PROGRAM_CNTXT_INIT(p, descbuf, 0);
+	if (ps)
+		PROGRAM_SET_36BIT_ADDR(p);
+
+	SHR_HDR(p, SHR_SERIAL, 1, 0);
+
+	/* Skip if already shared */
+	pskip_key_load = JUMP(p, skip_key_load, LOCAL_JUMP, ALL_TRUE, SHRD);
+	KEY(p, MDHA_SPLIT_KEY, authdata->key_enc_flags, authdata->key,
+	    authdata->keylen, INLINE_KEY(authdata));
+	SET_LABEL(p, skip_key_load);
+
+	/* Class 2 operation */
+	ALG_OPERATION(p, authdata->algtype & OP_ALG_ALGSEL_MASK,
+		      authdata->algtype & OP_ALG_AAI_MASK, OP_ALG_AS_INITFINAL,
+		      ICV_CHECK_ENABLE, DIR_DEC);
+
+	/* assoclen + cryptlen = seqinlen - authsize */
+	MATHB(p, SEQINSZ, SUB, icvsize, MATH3, CAAM_CMD_SZ, IMMED2);
+	/* assoclen = (assoclen + cryptlen) - cryptlen */
+	MATHB(p, SEQOUTSZ, SUB, MATH0, MATH2, CAAM_CMD_SZ, 0);
+	MATHB(p, MATH3, SUB, MATH2, VSEQINSZ, CAAM_CMD_SZ, 0);
+
+	/* read assoc before reading payload */
+	SEQFIFOLOAD(p, MSG2, 0 , VLF);
+
+	/* Prepare to read and write cryptlen bytes */
+	MATHB(p, ZERO, ADD, MATH2, VSEQINSZ, CAAM_CMD_SZ, 0);
+	MATHB(p, ZERO, ADD, MATH2, VSEQOUTSZ, CAAM_CMD_SZ, 0);
+
+	/*
+	 * MOVE_LEN opcode is not available in all SEC HW revisions,
+	 * thus need to do some magic, i.e. self-patch the descriptor buffer.
+	 */
+	pread_move_cmd = MOVE(p, DESCBUF, 0, MATH2, 0, 6, IMMED);
+	pwrite_move_cmd = MOVE(p, MATH2, 0, DESCBUF, 0, 8, WAITCOMP | IMMED);
+
+	/* Read and write cryptlen bytes */
+	SEQFIFOSTORE(p, MSG, 0, 0, VLF);
+	SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
+
+	/*
+	 * Insert a NOP here, since we need at least 4 instructions between
+	 * code patching the descriptor buffer and the location being patched.
+	 */
+	pnop_cmd = JUMP(p, nop_cmd, LOCAL_JUMP, ALL_TRUE, 0);
+	SET_LABEL(p, nop_cmd);
+
+	SET_LABEL(p, read_move_cmd);
+	SET_LABEL(p, write_move_cmd);
+	LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
+	MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
+	LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
+
+	/* Load ICV */
+	SEQFIFOLOAD(p, ICV2, icvsize, LAST2);
+
+	PATCH_JUMP(p, pskip_key_load, skip_key_load);
+	PATCH_JUMP(p, pnop_cmd, nop_cmd);
+	PATCH_MOVE(p, pread_move_cmd, read_move_cmd);
+	PATCH_MOVE(p, pwrite_move_cmd, write_move_cmd);
+
+	return PROGRAM_FINALIZE(p);
+}
+
+#endif /* __DESC_IPSEC_H__ */
-- 
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Kernel]     [Gnu Classpath]     [Gnu Crypto]     [DM Crypt]     [Netfilter]     [Bugtraq]

  Powered by Linux