crypto: caam - add support for rfc4543(gcm(aes))
authorTudor Ambarus <tudor.ambarus@freescale.com>
Thu, 30 Oct 2014 16:55:07 +0000 (18:55 +0200)
committerHerbert Xu <herbert@gondor.apana.org.au>
Thu, 6 Nov 2014 15:15:03 +0000 (23:15 +0800)
Add AES-GMAC as an IPSec ESP mechanism to provide
data origin authentication, but not confidentiality.
This method is referred as ENCR_NULL_AUTH_AES_GMAC.

Signed-off-by: Tudor Ambarus <tudor.ambarus@freescale.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/caam/caamalg.c

index 36434d9eefad18c8f1ab293d1ddcad9700845e7b..48df0520ed461aacd3e0d684f951952659db94be 100644 (file)
 #define DESC_RFC4106_DEC_LEN           (DESC_RFC4106_BASE + 14 * CAAM_CMD_SZ)
 #define DESC_RFC4106_GIVENC_LEN                (DESC_RFC4106_BASE + 21 * CAAM_CMD_SZ)
 
+#define DESC_RFC4543_BASE              (3 * CAAM_CMD_SZ)
+#define DESC_RFC4543_ENC_LEN           (DESC_RFC4543_BASE + 25 * CAAM_CMD_SZ)
+#define DESC_RFC4543_DEC_LEN           (DESC_RFC4543_BASE + 27 * CAAM_CMD_SZ)
+#define DESC_RFC4543_GIVENC_LEN                (DESC_RFC4543_BASE + 30 * 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)
 
-#define DESC_MAX_USED_BYTES            (DESC_AEAD_GIVENC_LEN + \
+#define DESC_MAX_USED_BYTES            (DESC_RFC4543_GIVENC_LEN + \
                                         CAAM_MAX_KEY_SIZE)
 #define DESC_MAX_USED_LEN              (DESC_MAX_USED_BYTES / CAAM_CMD_SZ)
 
@@ -1150,6 +1155,401 @@ static int rfc4106_setauthsize(struct crypto_aead *authenc,
        return 0;
 }
 
+static int rfc4543_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 *key_jump_cmd, *write_iv_cmd, *write_aad_cmd;
+       u32 *read_move_cmd, *write_move_cmd;
+       u32 *desc;
+       u32 geniv;
+
+       if (!ctx->enckeylen || !ctx->authsize)
+               return 0;
+
+       /*
+        * RFC4543 encrypt shared descriptor
+        * Job Descriptor and Shared Descriptor
+        * must fit into the 64-word Descriptor h/w Buffer
+        */
+       if (DESC_RFC4543_ENC_LEN + DESC_JOB_IO_LEN +
+           ctx->enckeylen <= CAAM_DESC_BYTES_MAX)
+               keys_fit_inline = true;
+
+       desc = ctx->sh_desc_enc;
+
+       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 (keys_fit_inline)
+               append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
+                                 ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
+       else
+               append_key(desc, ctx->key_dma, ctx->enckeylen,
+                          CLASS_1 | KEY_DEST_CLASS_REG);
+       set_jump_tgt_here(desc, key_jump_cmd);
+
+       /* Class 1 operation */
+       append_operation(desc, ctx->class1_alg_type |
+                        OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+
+       /* Load AES-GMAC ESP IV into Math1 register */
+       append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_WORD_DECO_MATH1 |
+                  LDST_CLASS_DECO | tfm->ivsize);
+
+       /* Wait the DMA transaction to finish */
+       append_jump(desc, JUMP_TEST_ALL | JUMP_COND_CALM |
+                   (1 << JUMP_OFFSET_SHIFT));
+
+       /* Overwrite blank immediate AES-GMAC ESP IV data */
+       write_iv_cmd = append_move(desc, MOVE_SRC_MATH1 | MOVE_DEST_DESCBUF |
+                                  (tfm->ivsize << MOVE_LEN_SHIFT));
+
+       /* Overwrite blank immediate AAD data */
+       write_aad_cmd = append_move(desc, MOVE_SRC_MATH1 | MOVE_DEST_DESCBUF |
+                                   (tfm->ivsize << MOVE_LEN_SHIFT));
+
+       /* cryptlen = seqoutlen - authsize */
+       append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize);
+
+       /* assoclen = (seqinlen - ivsize) - cryptlen */
+       append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG3, CAAM_CMD_SZ);
+
+       /* Read Salt and AES-GMAC ESP IV */
+       append_cmd(desc, CMD_FIFO_LOAD | FIFOLD_CLASS_CLASS1 | IMMEDIATE |
+                  FIFOLD_TYPE_IV | FIFOLD_TYPE_FLUSH1 | (4 + tfm->ivsize));
+       /* Append Salt */
+       append_data(desc, (void *)(ctx->key + ctx->enckeylen), 4);
+       set_move_tgt_here(desc, write_iv_cmd);
+       /* Blank commands. Will be overwritten by AES-GMAC ESP IV. */
+       append_cmd(desc, 0x00000000);
+       append_cmd(desc, 0x00000000);
+       /* End of blank commands */
+
+       /* Read assoc data */
+       append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
+                            FIFOLD_TYPE_AAD);
+
+       /* Will read cryptlen bytes */
+       append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
+
+       /* Will write cryptlen bytes */
+       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 |
+                                    (0x8 << MOVE_LEN_SHIFT));
+
+       /* Authenticate AES-GMAC ESP IV  */
+       append_cmd(desc, CMD_FIFO_LOAD | FIFOLD_CLASS_CLASS1 | IMMEDIATE |
+                  FIFOLD_TYPE_AAD | tfm->ivsize);
+       set_move_tgt_here(desc, write_aad_cmd);
+       /* Blank commands. Will be overwritten by AES-GMAC ESP IV. */
+       append_cmd(desc, 0x00000000);
+       append_cmd(desc, 0x00000000);
+       /* End of blank commands */
+
+       /* Read and write 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, ctx->authsize, LDST_CLASS_1_CCB |
+                        LDST_SRCDST_BYTE_CONTEXT);
+
+       ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc,
+                                             desc_bytes(desc),
+                                             DMA_TO_DEVICE);
+       if (dma_mapping_error(jrdev, ctx->sh_desc_enc_dma)) {
+               dev_err(jrdev, "unable to map shared descriptor\n");
+               return -ENOMEM;
+       }
+#ifdef DEBUG
+       print_hex_dump(KERN_ERR, "rfc4543 enc shdesc@"__stringify(__LINE__)": ",
+                      DUMP_PREFIX_ADDRESS, 16, 4, desc,
+                      desc_bytes(desc), 1);
+#endif
+
+       /*
+        * Job Descriptor and Shared Descriptors
+        * must all fit into the 64-word Descriptor h/w Buffer
+        */
+       keys_fit_inline = false;
+       if (DESC_RFC4543_DEC_LEN + DESC_JOB_IO_LEN +
+           ctx->enckeylen <= CAAM_DESC_BYTES_MAX)
+               keys_fit_inline = true;
+
+       desc = ctx->sh_desc_dec;
+
+       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 (keys_fit_inline)
+               append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
+                                 ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
+       else
+               append_key(desc, ctx->key_dma, ctx->enckeylen,
+                          CLASS_1 | KEY_DEST_CLASS_REG);
+       set_jump_tgt_here(desc, key_jump_cmd);
+
+       /* Class 1 operation */
+       append_operation(desc, ctx->class1_alg_type |
+                        OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT | OP_ALG_ICV_ON);
+
+       /* Load AES-GMAC ESP IV into Math1 register */
+       append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_WORD_DECO_MATH1 |
+                  LDST_CLASS_DECO | tfm->ivsize);
+
+       /* Wait the DMA transaction to finish */
+       append_jump(desc, JUMP_TEST_ALL | JUMP_COND_CALM |
+                   (1 << JUMP_OFFSET_SHIFT));
+
+       /* assoclen + cryptlen = (seqinlen - ivsize) - icvsize */
+       append_math_sub_imm_u32(desc, REG3, SEQINLEN, IMM, ctx->authsize);
+
+       /* Overwrite blank immediate AES-GMAC ESP IV data */
+       write_iv_cmd = append_move(desc, MOVE_SRC_MATH1 | MOVE_DEST_DESCBUF |
+                                  (tfm->ivsize << MOVE_LEN_SHIFT));
+
+       /* Overwrite blank immediate AAD data */
+       write_aad_cmd = append_move(desc, MOVE_SRC_MATH1 | MOVE_DEST_DESCBUF |
+                                   (tfm->ivsize << MOVE_LEN_SHIFT));
+
+       /* assoclen = (assoclen + cryptlen) - cryptlen */
+       append_math_sub(desc, REG2, SEQOUTLEN, REG0, CAAM_CMD_SZ);
+       append_math_sub(desc, VARSEQINLEN, REG3, 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_MATH3 |
+                                   (0x6 << MOVE_LEN_SHIFT));
+       write_move_cmd = append_move(desc, MOVE_SRC_MATH3 | MOVE_DEST_DESCBUF |
+                                    (0x8 << MOVE_LEN_SHIFT));
+
+       /* Read Salt and AES-GMAC ESP IV */
+       append_cmd(desc, CMD_FIFO_LOAD | FIFOLD_CLASS_CLASS1 | IMMEDIATE |
+                  FIFOLD_TYPE_IV | FIFOLD_TYPE_FLUSH1 | (4 + tfm->ivsize));
+       /* Append Salt */
+       append_data(desc, (void *)(ctx->key + ctx->enckeylen), 4);
+       set_move_tgt_here(desc, write_iv_cmd);
+       /* Blank commands. Will be overwritten by AES-GMAC ESP IV. */
+       append_cmd(desc, 0x00000000);
+       append_cmd(desc, 0x00000000);
+       /* End of blank commands */
+
+       /* Read assoc data */
+       append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
+                            FIFOLD_TYPE_AAD);
+
+       /* Will read cryptlen bytes */
+       append_math_add(desc, VARSEQINLEN, ZERO, REG2, CAAM_CMD_SZ);
+
+       /* Will write cryptlen bytes */
+       append_math_add(desc, VARSEQOUTLEN, ZERO, REG2, CAAM_CMD_SZ);
+
+       /* Authenticate AES-GMAC ESP IV  */
+       append_cmd(desc, CMD_FIFO_LOAD | FIFOLD_CLASS_CLASS1 | IMMEDIATE |
+                  FIFOLD_TYPE_AAD | tfm->ivsize);
+       set_move_tgt_here(desc, write_aad_cmd);
+       /* Blank commands. Will be overwritten by AES-GMAC ESP IV. */
+       append_cmd(desc, 0x00000000);
+       append_cmd(desc, 0x00000000);
+       /* End of blank commands */
+
+       /* Store payload data */
+       append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF);
+
+       /* In-snoop 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, ctx->authsize, FIFOLD_CLASS_CLASS1 |
+                            FIFOLD_TYPE_ICV | FIFOLD_TYPE_LAST1);
+
+       ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc,
+                                             desc_bytes(desc),
+                                             DMA_TO_DEVICE);
+       if (dma_mapping_error(jrdev, ctx->sh_desc_dec_dma)) {
+               dev_err(jrdev, "unable to map shared descriptor\n");
+               return -ENOMEM;
+       }
+#ifdef DEBUG
+       print_hex_dump(KERN_ERR, "rfc4543 dec shdesc@"__stringify(__LINE__)": ",
+                      DUMP_PREFIX_ADDRESS, 16, 4, desc,
+                      desc_bytes(desc), 1);
+#endif
+
+       /*
+        * Job Descriptor and Shared Descriptors
+        * must all fit into the 64-word Descriptor h/w Buffer
+        */
+       keys_fit_inline = false;
+       if (DESC_RFC4543_GIVENC_LEN + DESC_JOB_IO_LEN +
+           ctx->enckeylen <= CAAM_DESC_BYTES_MAX)
+               keys_fit_inline = true;
+
+       /* rfc4543_givencrypt shared descriptor */
+       desc = ctx->sh_desc_givenc;
+
+       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 (keys_fit_inline)
+               append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
+                                 ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
+       else
+               append_key(desc, ctx->key_dma, ctx->enckeylen,
+                          CLASS_1 | KEY_DEST_CLASS_REG);
+       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 | (tfm->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);
+       /* Move generated IV to Math1 register */
+       append_move(desc, MOVE_SRC_INFIFO | MOVE_DEST_MATH1 |
+                   (tfm->ivsize << MOVE_LEN_SHIFT));
+       append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
+
+       /* Overwrite blank immediate AES-GMAC IV data */
+       write_iv_cmd = append_move(desc, MOVE_SRC_MATH1 | MOVE_DEST_DESCBUF |
+                                  (tfm->ivsize << MOVE_LEN_SHIFT));
+
+       /* Overwrite blank immediate AAD data */
+       write_aad_cmd = append_move(desc, MOVE_SRC_MATH1 | MOVE_DEST_DESCBUF |
+                                   (tfm->ivsize << MOVE_LEN_SHIFT));
+
+       /* Copy generated IV to OFIFO */
+       append_move(desc, MOVE_SRC_MATH1 | MOVE_DEST_OUTFIFO |
+                   (tfm->ivsize << MOVE_LEN_SHIFT));
+
+       /* Class 1 operation */
+       append_operation(desc, ctx->class1_alg_type |
+                        OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+
+       /* ivsize + cryptlen = seqoutlen - authsize */
+       append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize);
+
+       /* assoclen = seqinlen - (ivsize + cryptlen) */
+       append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG3, CAAM_CMD_SZ);
+
+       /* Will write ivsize + cryptlen */
+       append_math_add(desc, VARSEQOUTLEN, REG3, 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));
+
+       /* Read Salt and AES-GMAC generated IV */
+       append_cmd(desc, CMD_FIFO_LOAD | FIFOLD_CLASS_CLASS1 | IMMEDIATE |
+                  FIFOLD_TYPE_IV | FIFOLD_TYPE_FLUSH1 | (4 + tfm->ivsize));
+       /* Append Salt */
+       append_data(desc, (void *)(ctx->key + ctx->enckeylen), 4);
+       set_move_tgt_here(desc, write_iv_cmd);
+       /* Blank commands. Will be overwritten by AES-GMAC generated IV. */
+       append_cmd(desc, 0x00000000);
+       append_cmd(desc, 0x00000000);
+       /* End of blank commands */
+
+       /* No need to reload iv */
+       append_seq_fifo_load(desc, tfm->ivsize, FIFOLD_CLASS_SKIP);
+
+       /* Read assoc data */
+       append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
+                            FIFOLD_TYPE_AAD);
+
+       /* Will read cryptlen */
+       append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+
+       /* Authenticate AES-GMAC IV  */
+       append_cmd(desc, CMD_FIFO_LOAD | FIFOLD_CLASS_CLASS1 | IMMEDIATE |
+                  FIFOLD_TYPE_AAD | tfm->ivsize);
+       set_move_tgt_here(desc, write_aad_cmd);
+       /* Blank commands. Will be overwritten by AES-GMAC IV. */
+       append_cmd(desc, 0x00000000);
+       append_cmd(desc, 0x00000000);
+       /* End of blank commands */
+
+       /* Read and write 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, ctx->authsize, LDST_CLASS_1_CCB |
+                        LDST_SRCDST_BYTE_CONTEXT);
+
+       ctx->sh_desc_givenc_dma = dma_map_single(jrdev, desc,
+                                                desc_bytes(desc),
+                                                DMA_TO_DEVICE);
+       if (dma_mapping_error(jrdev, ctx->sh_desc_givenc_dma)) {
+               dev_err(jrdev, "unable to map shared descriptor\n");
+               return -ENOMEM;
+       }
+#ifdef DEBUG
+       print_hex_dump(KERN_ERR,
+                      "rfc4543 givenc shdesc@"__stringify(__LINE__)": ",
+                      DUMP_PREFIX_ADDRESS, 16, 4, desc,
+                      desc_bytes(desc), 1);
+#endif
+
+       return 0;
+}
+
+static int rfc4543_setauthsize(struct crypto_aead *authenc,
+                              unsigned int authsize)
+{
+       struct caam_ctx *ctx = crypto_aead_ctx(authenc);
+
+       ctx->authsize = authsize;
+       rfc4543_set_sh_desc(authenc);
+
+       return 0;
+}
+
 static u32 gen_split_aead_key(struct caam_ctx *ctx, const u8 *key_in,
                              u32 authkeylen)
 {
@@ -1292,6 +1692,45 @@ static int rfc4106_setkey(struct crypto_aead *aead,
        return ret;
 }
 
+static int rfc4543_setkey(struct crypto_aead *aead,
+                         const u8 *key, unsigned int keylen)
+{
+       struct caam_ctx *ctx = crypto_aead_ctx(aead);
+       struct device *jrdev = ctx->jrdev;
+       int ret = 0;
+
+       if (keylen < 4)
+               return -EINVAL;
+
+#ifdef DEBUG
+       print_hex_dump(KERN_ERR, "key in @"__stringify(__LINE__)": ",
+                      DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1);
+#endif
+
+       memcpy(ctx->key, key, keylen);
+
+       /*
+        * The last four bytes of the key material are used as the salt value
+        * in the nonce. Update the AES key length.
+        */
+       ctx->enckeylen = keylen - 4;
+
+       ctx->key_dma = dma_map_single(jrdev, ctx->key, ctx->enckeylen,
+                                     DMA_TO_DEVICE);
+       if (dma_mapping_error(jrdev, ctx->key_dma)) {
+               dev_err(jrdev, "unable to map key i/o memory\n");
+               return -ENOMEM;
+       }
+
+       ret = rfc4543_set_sh_desc(aead);
+       if (ret) {
+               dma_unmap_single(jrdev, ctx->key_dma, ctx->enckeylen,
+                                DMA_TO_DEVICE);
+       }
+
+       return ret;
+}
+
 static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
                             const u8 *key, unsigned int keylen)
 {
@@ -3011,6 +3450,23 @@ static struct caam_alg_template driver_algs[] = {
                        },
                .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM,
        },
+       {
+               .name = "rfc4543(gcm(aes))",
+               .driver_name = "rfc4543-gcm-aes-caam",
+               .blocksize = 1,
+               .type = CRYPTO_ALG_TYPE_AEAD,
+               .template_aead = {
+                       .setkey = rfc4543_setkey,
+                       .setauthsize = rfc4543_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
+                       .givencrypt = aead_givencrypt,
+                       .geniv = "<built-in>",
+                       .ivsize = 8,
+                       .maxauthsize = AES_BLOCK_SIZE,
+                       },
+               .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM,
+       },
        /* Galois Counter Mode */
        {
                .name = "gcm(aes)",