diff mbox

[U-Boot,v3] imx6: Added DEK blob generator command

Message ID 1423756792-9274-1-git-send-email-Ulises.Cardenas@freescale.com
State Changes Requested
Headers show

Commit Message

Ulises.Cardenas@freescale.com Feb. 12, 2015, 3:59 p.m. UTC
From: Raul Cardenas <Ulises.Cardenas@freescale.com>

Freescale's SEC block has built-in Data Encryption
Key(DEK) Blob Protocol which provides a method for
protecting a DEK for non-secure memory storage.
SEC block protects data in a data structure called
a Secret Key Blob, which provides both confidentiality
and integrity protection.
Every time the blob encapsulation is executed,
a SHA-256 key is randomly generated to encrypt the DEK.
This key is itself encrypted with the OTP Secret key
from SoC. The ending blob consists of the encrypted
SHA-256 key, the encrypted DEK, and a 16-bit MAC.

During decapsulation, the reverse process is performed
to get back the original DEK. A caveat to the blob
decapsulation process,  is that the DEK is decrypted
in secure-memory and can only be read by FSL SEC HW.
The DEK is used to decrypt data during encrypted boot.

Commands added
--------------
  dek_blob - encapsulating DEK as a cryptgraphic blob

Commands Syntax
---------------
  dek_blob src dst len

    Encapsulate and create blob of a len-bits DEK at
    address src and store the result at address dst.

Signed-off-by: Raul Cardenas <Ulises.Cardenas@freescale.com>
Signed-off-by: Nitin Garg <nitin.garg@freescale.com>

---

Changes in v3:
-Improve cache management for relevant descriptors
-Add cache management to RNG instantiate

Changes in v2:
-Remove weak symbol as recommended by Ruchika

 arch/arm/imx-common/Makefile             |    1 +
 arch/arm/imx-common/cmd_dek.c            |   89 +++++++++++++++++++
 arch/arm/imx-common/timer.c              |   17 ++++
 arch/arm/include/asm/arch-mx6/imx-regs.h |    4 +
 doc/README.mxc_hab                       |   48 ++++++++++
 drivers/crypto/fsl/Makefile              |    2 +-
 drivers/crypto/fsl/desc.h                |   15 ++++
 drivers/crypto/fsl/fsl_blob.c            |   50 +++++++++++
 drivers/crypto/fsl/jobdesc.c             |  142 +++++++++++++++++++++++++++++-
 drivers/crypto/fsl/jobdesc.h             |    5 ++
 drivers/crypto/fsl/jr.c                  |   31 ++++++-
 include/fsl_sec.h                        |   60 +++++++++++++
 12 files changed, 457 insertions(+), 7 deletions(-)
 create mode 100644 arch/arm/imx-common/cmd_dek.c

Comments

Simon Glass Feb. 13, 2015, 10:53 p.m. UTC | #1
Hi,

On 12 February 2015 at 08:59, <Ulises.Cardenas@freescale.com> wrote:
>
> From: Raul Cardenas <Ulises.Cardenas@freescale.com>

Some comments from me since I was copied. Just code style.

>
> Freescale's SEC block has built-in Data Encryption
> Key(DEK) Blob Protocol which provides a method for
> protecting a DEK for non-secure memory storage.
> SEC block protects data in a data structure called
> a Secret Key Blob, which provides both confidentiality
> and integrity protection.
> Every time the blob encapsulation is executed,
> a SHA-256 key is randomly generated to encrypt the DEK.


should this say 'hash' rather than key? Normally SHA-256 is used to
generate a hash from known data, not a random number.

>
> This key is itself encrypted with the OTP Secret key
> from SoC. The ending blob consists of the encrypted
> SHA-256 key, the encrypted DEK, and a 16-bit MAC.


s/key/hash/ again?

>
>
> During decapsulation, the reverse process is performed
> to get back the original DEK. A caveat to the blob
> decapsulation process,  is that the DEK is decrypted
> in secure-memory and can only be read by FSL SEC HW.
> The DEK is used to decrypt data during encrypted boot.
>
> Commands added
> --------------
>   dek_blob - encapsulating DEK as a cryptgraphic blob
>
> Commands Syntax
> ---------------
>   dek_blob src dst len
>
>     Encapsulate and create blob of a len-bits DEK at
>     address src and store the result at address dst.
>
> Signed-off-by: Raul Cardenas <Ulises.Cardenas@freescale.com>
> Signed-off-by: Nitin Garg <nitin.garg@freescale.com>
>
> ---
>
> Changes in v3:
> -Improve cache management for relevant descriptors
> -Add cache management to RNG instantiate
>
> Changes in v2:
> -Remove weak symbol as recommended by Ruchika
>
>  arch/arm/imx-common/Makefile             |    1 +
>  arch/arm/imx-common/cmd_dek.c            |   89 +++++++++++++++++++
>  arch/arm/imx-common/timer.c              |   17 ++++
>  arch/arm/include/asm/arch-mx6/imx-regs.h |    4 +
>  doc/README.mxc_hab                       |   48 ++++++++++
>  drivers/crypto/fsl/Makefile              |    2 +-
>  drivers/crypto/fsl/desc.h                |   15 ++++
>  drivers/crypto/fsl/fsl_blob.c            |   50 +++++++++++
>  drivers/crypto/fsl/jobdesc.c             |  142 +++++++++++++++++++++++++++++-
>  drivers/crypto/fsl/jobdesc.h             |    5 ++
>  drivers/crypto/fsl/jr.c                  |   31 ++++++-
>  include/fsl_sec.h                        |   60 +++++++++++++
>  12 files changed, 457 insertions(+), 7 deletions(-)
>  create mode 100644 arch/arm/imx-common/cmd_dek.c
>
> diff --git a/arch/arm/imx-common/Makefile b/arch/arm/imx-common/Makefile
> index 25a9d4c..606482f 100644
> --- a/arch/arm/imx-common/Makefile
> +++ b/arch/arm/imx-common/Makefile
> @@ -24,6 +24,7 @@ obj-$(CONFIG_IMX_VIDEO_SKIP) += video.o
>  endif
>  obj-$(CONFIG_CMD_BMODE) += cmd_bmode.o
>  obj-$(CONFIG_CMD_HDMIDETECT) += cmd_hdmidet.o
> +obj-$(CONFIG_CMD_DEKBLOB) += cmd_dek.o
>
>  quiet_cmd_cpp_cfg = CFGS    $@
>        cmd_cpp_cfg = $(CPP) $(cpp_flags) -x c -o $@ $<
> diff --git a/arch/arm/imx-common/cmd_dek.c b/arch/arm/imx-common/cmd_dek.c
> new file mode 100644
> index 0000000..1a3a996a
> --- /dev/null
> +++ b/arch/arm/imx-common/cmd_dek.c
> @@ -0,0 +1,89 @@
> +/*
> + * Command for encapsulating DEK blob
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <command.h>
> +#include <environment.h>
> +#include <malloc.h>
> +#include <asm/byteorder.h>
> +#include <linux/compiler.h>
> +#include <fsl_sec.h>
> +#include <asm/arch/clock.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/**
> +* blob_dek() - Encapsulate the DEK as a blob using CAM's Key
> +* @src: - Address of data to be encapsulated
> +* @dst: - Address of data to be encapsulated

Why are these the same?

> +* @len: - Size of data to be encapsulated
> +*
> +* Returns zero on success,and negative on error.
> +*/
> +static int blob_encap_dek(u8 *src, u8 *dst, u32 len)

const u8 *src ?

> +{
> +       int ret = 0;
> +       u32 jr_size = 4;
> +
> +       u32 out_jr_size = sec_in32(CONFIG_SYS_FSL_JR0_ADDR + 0x102c);
> +       if (out_jr_size != jr_size) {
> +               hab_caam_clock_enable(1);
> +               sec_init();
> +       }
> +
> +       if (!((len == 128)|(len == 192)|(len == 256))) {


spaces around operators like |

>
> +               debug("Invalid DEK size. Valid sizes are 128, 192 and 256b\n");
> +               return -1;
> +       }
> +
> +       len /= 8;
> +       ret = blob_dek(src, dst, len);
> +
> +       return ret;
> +}
> +
> +/**
> + * do_dek_blob() - Handle the "dek_blob" command-line command
> + * @cmdtp:  Command data struct pointer
> + * @flag:   Command flag
> + * @argc:   Command-line argument count
> + * @argv:   Array of command-line arguments
> + *
> + * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
> + * on error.
> + */
> +static int do_dek_blob(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
> +{
> +       uint32_t src_addr, dst_addr, len;
> +       uint8_t *src_ptr, *dst_ptr;
> +       int ret = 0;
> +
> +       if (argc != 4)
> +               return CMD_RET_USAGE;
> +
> +       src_addr = simple_strtoul(argv[1], NULL, 16);
> +       dst_addr = simple_strtoul(argv[2], NULL, 16);
> +       len = simple_strtoul(argv[3], NULL, 10);
> +
> +       src_ptr = (uint8_t *)src_addr;
> +       dst_ptr = (uint8_t *)dst_addr;

src_ptr = map_sysmem(src_addr, len);
dst_ptr = map_sysmem(src_addr, len);

> +
> +       ret = blob_encap_dek(src_ptr, dst_ptr, len);
> +
> +       return ret;
> +}
> +
> +/***************************************************/
> +static char dek_blob_help_text[] =
> +       "src dst len            - Encapsulate and create blob of data\n"
> +       "                         $len bits long at address $src and\n"
> +       "                         store the result at address $dst.\n";
> +
> +U_BOOT_CMD(
> +       dek_blob, 4, 1, do_dek_blob,
> +       "Data Encryption Key blob encapsulation",
> +       dek_blob_help_text
> +);
> diff --git a/arch/arm/imx-common/timer.c b/arch/arm/imx-common/timer.c
> index 65ef60b..e522990 100644
> --- a/arch/arm/imx-common/timer.c
> +++ b/arch/arm/imx-common/timer.c
> @@ -176,3 +176,20 @@ ulong get_tbclk(void)
>  {
>         return gpt_get_clk();
>  }
> +
> +/*
> + * This function is intended for SHORT delays only.
> + * It will overflow at around 10 seconds @ 400MHz,
> + * or 20 seconds @ 200MHz.
> + */
> +unsigned long usec2ticks(unsigned long usec)
> +{
> +       ulong ticks;
> +
> +       if (usec < 1000)
> +               ticks = ((usec * (get_tbclk()/1000)) + 500) / 1000;
> +       else
> +               ticks = ((usec / 10) * (get_tbclk() / 100000));
> +
> +       return ticks;
> +}
> diff --git a/arch/arm/include/asm/arch-mx6/imx-regs.h b/arch/arm/include/asm/arch-mx6/imx-regs.h
> index ae88b6e..065b27b 100644
> --- a/arch/arm/include/asm/arch-mx6/imx-regs.h
> +++ b/arch/arm/include/asm/arch-mx6/imx-regs.h
> @@ -215,6 +215,10 @@
>  #define AIPS2_OFF_BASE_ADDR         (ATZ2_BASE_ADDR + 0x80000)
>  #define CAAM_BASE_ADDR              (ATZ2_BASE_ADDR)
>  #define ARM_BASE_ADDR              (ATZ2_BASE_ADDR + 0x40000)
> +
> +#define CONFIG_SYS_FSL_SEC_ADDR     (CAAM_BASE_ADDR)
> +#define CONFIG_SYS_FSL_JR0_ADDR     (CAAM_BASE_ADDR + 0x1000)
> +
>  #define USB_PL301_BASE_ADDR         (AIPS2_OFF_BASE_ADDR + 0x0000)
>  #define USB_BASE_ADDR               (AIPS2_OFF_BASE_ADDR + 0x4000)
>
> diff --git a/doc/README.mxc_hab b/doc/README.mxc_hab
> index 43e64a2..46ed0df 100644
> --- a/doc/README.mxc_hab
> +++ b/doc/README.mxc_hab
> @@ -46,3 +46,51 @@ cat u-boot.imx U-Boot_CSF_pad.bin > u-boot-signed.imx
>
>  NOTE: U-Boot_CSF.bin needs to be padded to the value specified in
>  the imximage.cfg file.
> +
> +Setup U-Boot Image for Encrypted Boot
> +-------------------------------------
> +An authenticated  U-boot image  is used as starting point for

s/  / /g

See more double spaces below.

> +Encrypted Boot. The image is encrypted by Freescale's Code
> +Signing Tool (CST). The CST replaces only the image data of
> +u-boot.imx with the encrypted data. The Initial Vector Table,
> +DCD, and Boot data, remains in plaintext.
> +
> +The image data  is encrypted with a Encryption Key (DEK).
> +Therefore, this key is needed to decrypt the data during the
> +booting process. The DEK is protected by wrapping it in a Blob,
> +which needs to be appended to the U-boot image and specified in

U-Boot (fix globally)

> +the CSF file.
> +
> +The DEK blob is generated by an authenticated U-boot image with
> +the dek_blob cmd enabled. The image used for DEK blob generation
> +needs to have the following configurations enabled:
> +
> +CONFIG_SECURE_BOOT
> +CONFIG_SYS_FSL_SEC_COMPAT    4 /* HAB version */
> +CONFIG_FSL_CAAM
> +CONFIG_CMD_DEKBLOB
> +
> +Note: The encrypted boot feature is only supported by HABv4 or
> +greater.
> +
> +The dek_blob command then can be used to generate the DEK blob of
> +a DEK previously loaded in memory. The command is used as follows:
> +
> +dek_blob <DEK address>  <Output Address> <Key Size in Bits>
> +example:  dek_blob 0x10800000 0x10801000 192
> +
> +The resulting DEK blob then is used to construct the encrypted
> +U-boot image. Note that the blob needs to be transfered back

transferred

> +to the host.Then the following commands are used to construct
> +the final image.
> +
> +objcopy -I binary -O binary --pad-to 0x2000 --gap-fill=0x00 \
> +    U-Boot_CSF.bin U-Boot_CSF_pad.bin
> +cat u-boot.imx U-Boot_CSF_pad.bin > u-boot-signed.imx
> +objcopy -I binary -O binary --pad-to <blob_dst> --gap-fill=0x00 \
> +    u-boot-signed.imx u-boot-signed-pad.bin
> +cat u-boot-signed-pad.imx DEK_blob.bin > u-boot-encrypted.imx
> +
> +    NOTE: u-boot-signed.bin needs to be padded to the value
> +    equivalent to the address in which the DEK blob is specified
> +    in the CSF.
> diff --git a/drivers/crypto/fsl/Makefile b/drivers/crypto/fsl/Makefile
> index c0cf642..4aa91e4 100644
> --- a/drivers/crypto/fsl/Makefile
> +++ b/drivers/crypto/fsl/Makefile
> @@ -8,5 +8,5 @@
>
>  obj-y += sec.o
>  obj-$(CONFIG_FSL_CAAM) += jr.o fsl_hash.o jobdesc.o error.o
> -obj-$(CONFIG_CMD_BLOB) += fsl_blob.o
> +obj-$(CONFIG_CMD_BLOB)$(CONFIG_CMD_DEKBLOB) += fsl_blob.o
>  obj-$(CONFIG_RSA_FREESCALE_EXP) += fsl_rsa.o
> diff --git a/drivers/crypto/fsl/desc.h b/drivers/crypto/fsl/desc.h
> index 504f2b0..bb82734 100644
> --- a/drivers/crypto/fsl/desc.h
> +++ b/drivers/crypto/fsl/desc.h
> @@ -12,11 +12,18 @@
>  #ifndef DESC_H
>  #define DESC_H
>
> +#define KEY_BLOB_SIZE          32
> +#define MAC_SIZE               16
> +
>  /* Max size of any CAAM descriptor in 32-bit words, inclusive of header */
>  #define MAX_CAAM_DESCSIZE      64
>
> +/* Size of DEK Blob  descriptor, inclusive of header */
> +#define DEK_BLOB_DESCSIZE      9
> +
>  /* Block size of any entity covered/uncovered with a KEK/TKEK */
>  #define KEK_BLOCKSIZE          16
> +
>  /*
>   * Supported descriptor command types as they show up
>   * inside a descriptor command word.
> @@ -273,6 +280,13 @@
>  #define LDLEN_SET_OFIFO_OFFSET_MASK    (3 << LDLEN_SET_OFIFO_OFFSET_SHIFT)
>
>  /*
> + * AAD Definitions
> + */
> +#define AES_KEY_SHIFT          8
> +#define LD_CCM_MODE            (0x66)
> +#define KEY_AES_SRC            (0x55 << AES_KEY_SHIFT)
> +
> +/*
>   * FIFO_LOAD/FIFO_STORE/SEQ_FIFO_LOAD/SEQ_FIFO_STORE
>   * Command Constructs
>   */
> @@ -418,6 +432,7 @@
>  #define OP_PCLID_MASK          (0xff << 16)
>
>  /* Assuming OP_TYPE = OP_TYPE_UNI_PROTOCOL */
> +#define OP_PCLID_SECMEM                (0x08)

Remove ()

>  #define OP_PCLID_BLOB          (0x0d << OP_PCLID_SHIFT)
>  #define OP_PCLID_SECRETKEY     (0x11 << OP_PCLID_SHIFT)
>  #define OP_PCLID_PUBLICKEYPAIR (0x14 << OP_PCLID_SHIFT)
> diff --git a/drivers/crypto/fsl/fsl_blob.c b/drivers/crypto/fsl/fsl_blob.c
> index bc01075..f9dc85a 100644
> --- a/drivers/crypto/fsl/fsl_blob.c
> +++ b/drivers/crypto/fsl/fsl_blob.c
> @@ -7,6 +7,7 @@
>
>  #include <common.h>
>  #include <malloc.h>
> +#include <fsl_sec.h>
>  #include "jobdesc.h"
>  #include "desc.h"
>  #include "jr.h"
> @@ -59,3 +60,52 @@ int blob_encrypt(u8 *key_mod, u8 *src, u8 *dst, u8 len)
>         free(desc);
>         return ret;
>  }
> +
> +#ifdef CONFIG_CMD_DEKBLOB
> +int blob_dek(u8 *src, u8 *dst, u8 len)

const u8 *src ?

> +{
> +       int ret, size, i = 0;
> +       u32 *desc;
> +
> +       int out_sz =  WRP_HDR_SIZE + len + KEY_BLOB_SIZE + MAC_SIZE;
> +
> +       puts("\nEncapsulating provided DEK to form blob\n");
> +       desc = memalign(ARCH_DMA_MINALIGN,
> +                       sizeof(uint32_t) * DEK_BLOB_DESCSIZE);
> +       if (!desc) {
> +               debug("Not enough memory for descriptor allocation\n");
> +               return -1;

-ENOMEM

> +       }
> +
> +       ret = inline_cnstr_jobdesc_blob_dek(desc, src, dst, len);
> +       if (ret) {
> +               debug("Error in Job Descriptor Construction:  %d\n", ret);
> +       } else {
> +               size = roundup(sizeof(uint32_t) * DEK_BLOB_DESCSIZE,
> +                             ARCH_DMA_MINALIGN);
> +               flush_dcache_range((unsigned long)desc,
> +                                  (unsigned long)desc + size);
> +               size = roundup(sizeof(uint8_t) * out_sz, ARCH_DMA_MINALIGN);
> +               flush_dcache_range((unsigned long)dst,
> +                                  (unsigned long)dst + size);
> +
> +               ret = run_descriptor_jr(desc);
> +       }
> +
> +       if (ret)
> +               debug("Error in Encapsulation %d\n", ret);
> +

Should it be 'encapsulation'?

'goto err' here?

> +       size = roundup(out_sz, ARCH_DMA_MINALIGN);
> +       invalidate_dcache_range((unsigned long)dst, (unsigned long)dst+size);
> +
> +       /* Print DEK Blob */
> +       puts("DEK Blob\n");
> +       for (i = 0; i < out_sz; i++)
> +               printf("%02X", ((uint8_t *)dst)[i]);

Could use print_buffer() if it is large.

> +
> +       puts("\n\n");

printf() now I believe

err:

> +
> +       free(desc);
> +       return ret;
> +}
> +#endif
> diff --git a/drivers/crypto/fsl/jobdesc.c b/drivers/crypto/fsl/jobdesc.c
> index cc0dced..4dc73ae 100644
> --- a/drivers/crypto/fsl/jobdesc.c
> +++ b/drivers/crypto/fsl/jobdesc.c
> @@ -9,12 +9,150 @@
>   */
>
>  #include <common.h>
> +#include <fsl_sec.h>
>  #include "desc_constr.h"
>  #include "jobdesc.h"
>  #include "rsa_caam.h"
>
> -#define KEY_BLOB_SIZE                  32
> -#define MAC_SIZE                       16
> +#ifdef CONFIG_MX6
> +/*!
> + * Secure memory run command.

What does this function do?

> + *
> + * @param   sec_mem_cmd  Secure memory command register
> + * @return  cmd_status  Secure memory command status register
> + */
> +uint32_t secmem_set_cmd(uint32_t sec_mem_cmd)
> +{
> +       uint32_t temp_reg;
> +
> +       sec_out32(CAAM_SMCJR0, sec_mem_cmd);
> +
> +       do {
> +               temp_reg = sec_in32(CAAM_SMCSJR0);
> +       } while (temp_reg & CMD_COMPLETE);
> +
> +       return temp_reg;
> +}
> +
> +/*!
> + * CAAM page allocation.

Sure, but you should document what this function does.

> + *
> + * @param   page  Number of the page to allocate.
> + * @param   partition  Number of the partition to allocate.

@return ...

> + */
> +uint32_t caam_page_alloc(uint8_t page_num, uint8_t partition_num)

Perhaps returning int would be better so you can return an errno error

> +{
> +       uint32_t temp_reg;
> +
> +       /*
> +        * De-Allocate partition_num if already allocated to ARM core
> +        */
> +       if (sec_in32(CAAM_SMPO_0) & PARTITION_OWNER(partition_num)) {
> +               temp_reg = secmem_set_cmd(PARTITION(partition_num) |
> +                                               CMD_PART_DEALLOC);
> +               if (temp_reg & SMCSJR_AERR) {
> +                       printf("Error: De-allocation status 0x%X\n", temp_reg);
> +                       return ERROR_IN_PAGE_ALLOC;
> +               }
> +       }
> +
> +       /* set the access rights to allow full access */
> +       sec_out32(CAAM_SMAG1JR0(partition_num), 0xF);
> +       sec_out32(CAAM_SMAG2JR0(partition_num), 0xF);
> +       sec_out32(CAAM_SMAPJR0(partition_num), 0xFF);
> +
> +       /* Now need to allocate partition_num of secure RAM. */
> +       /* De-Allocate page_num by starting with a page inquiry command */
> +       temp_reg = secmem_set_cmd(PAGE(page_num) | CMD_INQUIRY);
> +
> +       /* if the page is owned, de-allocate it */
> +       if ((temp_reg & SMCSJR_PO) == PAGE_OWNED) {
> +               temp_reg = secmem_set_cmd(PAGE(page_num) | CMD_PAGE_DEALLOC);
> +               if (temp_reg & SMCSJR_AERR) {
> +                       printf("Error: Allocation status 0x%X\n", temp_reg);
> +                       return ERROR_IN_PAGE_ALLOC;
> +               }
> +       }
> +
> +       /* Allocate page_num to partition_num */
> +       temp_reg = secmem_set_cmd(PAGE(page_num) | PARTITION(partition_num)
> +                                               | CMD_PAGE_ALLOC);
> +       if (temp_reg & SMCSJR_AERR) {
> +               printf("Error: Allocation status 0x%X\n", temp_reg);
> +               return ERROR_IN_PAGE_ALLOC;
> +       }
> +       /* page inquiry command to ensure that the page was allocated */
> +       temp_reg = secmem_set_cmd(PAGE(page_num) | CMD_INQUIRY);
> +
> +       /* if the page is not owned => problem */
> +       if ((temp_reg & SMCSJR_PO) != PAGE_OWNED) {
> +               printf("Allocation of page %d in partition %d failed 0x%X\n",
> +                      temp_reg, page_num, partition_num);
> +
> +               return ERROR_IN_PAGE_ALLOC;
> +       }
> +
> +       return 0;
> +}
> +
> +uint32_t inline_cnstr_jobdesc_blob_dek(uint32_t *desc, uint8_t *plain_txt,
> +                                      uint8_t *dek_blob, uint32_t in_sz)

Why inline? Suggest returning int so you can return an error.

> +{
> +       uint32_t ret = 0;
> +       u32 aad_w1, aad_w2;
> +       /* output blob will have 32 bytes key blob in beginning and
> +        * 16 byte HMAC identifier at end of data blob */
> +       uint32_t out_sz = in_sz + KEY_BLOB_SIZE + MAC_SIZE;
> +       /* Setting HDR for blob */
> +       uint8_t wrapped_key_hdr[8] = {HDR_TAG, 0x00, WRP_HDR_SIZE + out_sz,
> +                                    HDR_PAR, HAB_MOD, HAB_ALG, in_sz, HAB_FLG};
> +
> +       /* initialize the blob array */
> +       memset(dek_blob, 0, out_sz + 8);
> +       /* Copy the header into the DEK blob buffer */
> +       memcpy((uint32_t *)dek_blob, wrapped_key_hdr, sizeof(wrapped_key_hdr));

You don't need the uint32_t type.

BTW is wrapped_key_hdr a typedef? You could change it to use 'struct
wrapped_key_hdr' sometime.

> +
> +       /* allocating secure memory */
> +       ret = caam_page_alloc(PAGE_1, PARTITION_1);
> +       if (ret)
> +               return ret;
> +
> +       /* Write DEK to secure memory */
> +       memcpy((uint32_t *)SEC_MEM_PAGE1, (uint32_t *)plain_txt, in_sz);
> +
> +       unsigned long start = (unsigned long)SEC_MEM_PAGE1 &
> +                               ~(ARCH_DMA_MINALIGN - 1);
> +       unsigned long end = ALIGN(start + 0x1000, ARCH_DMA_MINALIGN);
> +       flush_dcache_range(start, end);
> +
> +       /* Now configure the access rights of the partition */
> +       sec_out32(CAAM_SMAG1JR0(PARTITION_1), KS_G1); /* set group 1 */
> +       sec_out32(CAAM_SMAG2JR0(PARTITION_1), 0);     /* clear group 2 */
> +       sec_out32(CAAM_SMAPJR0(PARTITION_1), PERM);   /* set perm & locks */
> +
> +       /* construct aad for AES */
> +       aad_w1 = (in_sz << OP_ALG_ALGSEL_SHIFT) | KEY_AES_SRC | LD_CCM_MODE;
> +       aad_w2 = 0x0;
> +
> +       init_job_desc(desc, 0);
> +
> +       append_cmd(desc, CMD_LOAD | CLASS_2 | KEY_IMM | KEY_ENC |
> +                               (0x0c << LDST_OFFSET_SHIFT) | 0x08);
> +
> +       append_u32(desc, aad_w1);
> +
> +       append_u32(desc, aad_w2);
> +
> +       append_cmd_ptr(desc, (dma_addr_t)SEC_MEM_PAGE1, in_sz, CMD_SEQ_IN_PTR);
> +
> +       append_cmd_ptr(desc, (dma_addr_t)dek_blob + 8, out_sz, CMD_SEQ_OUT_PTR);
> +
> +       append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB |
> +                                               OP_PCLID_SECMEM);
> +
> +       return ret;
> +}
> +#endif
>
>  void inline_cnstr_jobdesc_hash(uint32_t *desc,
>                           const uint8_t *msg, uint32_t msgsz, uint8_t *digest,
> diff --git a/drivers/crypto/fsl/jobdesc.h b/drivers/crypto/fsl/jobdesc.h
> index 84b3edd..d20c18c 100644
> --- a/drivers/crypto/fsl/jobdesc.h
> +++ b/drivers/crypto/fsl/jobdesc.h
> @@ -14,6 +14,11 @@
>
>  #define KEY_IDNFR_SZ_BYTES             16

comment?

>
> +#ifdef CONFIG_CMD_DEKBLOB

Function comment

> +uint32_t inline_cnstr_jobdesc_blob_dek(uint32_t *desc, uint8_t *plain_txt,
> +                               uint8_t *enc_blob, uint32_t in_sz);
> +#endif
> +
>  void inline_cnstr_jobdesc_hash(uint32_t *desc,
>                           const uint8_t *msg, uint32_t msgsz, uint8_t *digest,
>                           u32 alg_type, uint32_t alg_size, int sg_tbl);
> diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c
> index f9d4938..f99d594 100644
> --- a/drivers/crypto/fsl/jr.c
> +++ b/drivers/crypto/fsl/jr.c
> @@ -90,11 +90,13 @@ static int jr_init(void)
>         jr.liodn = DEFAULT_JR_LIODN;
>  #endif
>         jr.size = JR_SIZE;
> -       jr.input_ring = (dma_addr_t *)malloc(JR_SIZE * sizeof(dma_addr_t));
> +       jr.input_ring = (dma_addr_t *)memalign(ARCH_DMA_MINALIGN,
> +                               JR_SIZE * sizeof(dma_addr_t));
>         if (!jr.input_ring)
>                 return -1;
>         jr.output_ring =
> -           (struct op_ring *)malloc(JR_SIZE * sizeof(struct op_ring));
> +           (struct op_ring *)memalign(ARCH_DMA_MINALIGN,
> +                               JR_SIZE * sizeof(struct op_ring));
>         if (!jr.output_ring)
>                 return -1;
>
> @@ -163,13 +165,23 @@ static int jr_enqueue(uint32_t *desc_addr,
>             CIRC_SPACE(jr.head, jr.tail, jr.size) <= 0)
>                 return -1;
>
> -       jr.input_ring[head] = desc_phys_addr;
>         jr.info[head].desc_phys_addr = desc_phys_addr;
>         jr.info[head].desc_addr = (uint32_t)desc_addr;
>         jr.info[head].callback = (void *)callback;
>         jr.info[head].arg = arg;
>         jr.info[head].op_done = 0;
>
> +       unsigned long start = (unsigned long)&jr.info[head] &
> +                                       ~(ARCH_DMA_MINALIGN - 1);
> +       unsigned long end = ALIGN(start + sizeof(struct jr_info),
> +                                       ARCH_DMA_MINALIGN);
> +       flush_dcache_range(start, end);
> +
> +       jr.input_ring[head] = desc_phys_addr;
> +       start = (unsigned long)&jr.input_ring[head] & ~(ARCH_DMA_MINALIGN - 1);
> +       end = ALIGN(start + sizeof(dma_addr_t), ARCH_DMA_MINALIGN);
> +       flush_dcache_range(start, end);
> +
>         jr.head = (head + 1) & (jr.size - 1);
>
>         sec_out32(&regs->irja, 1);
> @@ -187,6 +199,13 @@ static int jr_dequeue(void)
>         void *arg = NULL;
>
>         while (sec_in32(&regs->orsf) && CIRC_CNT(jr.head, jr.tail, jr.size)) {
> +               unsigned long start = (unsigned long)jr.output_ring &
> +                                       ~(ARCH_DMA_MINALIGN - 1);
> +               unsigned long end = ALIGN(start +
> +                                         sizeof(struct op_ring)*JR_SIZE,
> +                                         ARCH_DMA_MINALIGN);
> +               invalidate_dcache_range(start, end);
> +
>                 found = 0;
>
>                 dma_addr_t op_desc = jr.output_ring[jr.tail].desc;
> @@ -333,13 +352,17 @@ static int instantiate_rng(void)
>
>         memset(&op, 0, sizeof(struct result));
>
> -       desc = malloc(sizeof(int) * 6);
> +       desc = memalign(ARCH_DMA_MINALIGN, sizeof(uint32_t) * 6);
>         if (!desc) {
>                 printf("cannot allocate RNG init descriptor memory\n");
>                 return -1;
>         }
>
>         inline_cnstr_jobdesc_rng_instantiation(desc);
> +       int size = roundup(sizeof(uint32_t) * 6, ARCH_DMA_MINALIGN);
> +       flush_dcache_range((unsigned long)desc,
> +                          (unsigned long)desc + size);
> +
>         ret = run_descriptor_jr(desc);
>
>         if (ret)
> diff --git a/include/fsl_sec.h b/include/fsl_sec.h
> index aa850a3..95fbb6b 100644
> --- a/include/fsl_sec.h
> +++ b/include/fsl_sec.h
> @@ -11,6 +11,13 @@
>  #include <common.h>
>  #include <asm/io.h>
>
> +#ifdef CONFIG_ARM
> +#define sec_in32(a)       __raw_readl(a)
> +#define sec_out32(a, v)   __raw_writel(v, a)
> +#define sec_in16(a)       __raw_readw(a)
> +#define sec_clrbits32     clrbits_le32
> +#define sec_setbits32     setbits_le32

Does PPC not have clrbits_le32() etc.?

> +#elif CONFIG_PPC
>  #ifdef CONFIG_SYS_FSL_SEC_LE
>  #define sec_in32(a)       in_le32(a)
>  #define sec_out32(a, v)   out_le32(a, v)
> @@ -26,6 +33,7 @@
>  #else
>  #error Neither CONFIG_SYS_FSL_SEC_LE nor CONFIG_SYS_FSL_SEC_BE is defined
>  #endif
> +#endif      /* ARCHITECURE */

ARCHITECTURE

>
>  /* Security Engine Block (MS = Most Sig., LS = Least Sig.) */
>  #if CONFIG_SYS_FSL_SEC_COMPAT >= 4
> @@ -175,7 +183,59 @@ struct jr_regs {
>         u32 jrcr;
>  };
>
> +#ifdef CONFIG_MX6
> +
> +#define SMCSJR_PO              (3 << 6)
> +#define SMCSJR_AERR            (3 << 12)
> +#define SMCSJR_CERR            (3 << 14)
> +#define CAAM_SMPO_0            CONFIG_SYS_FSL_SEC_ADDR + 0x1FBC
> +#define CAAM_SMCJR0            CONFIG_SYS_FSL_SEC_ADDR + 0x10f4
> +#define CAAM_SMCSJR0           CONFIG_SYS_FSL_SEC_ADDR + 0x10fc
> +#define CAAM_SMAPJR0(y)                (CONFIG_SYS_FSL_SEC_ADDR + 0x1104 + y*16)
> +#define CAAM_SMAG2JR0(y)       (CONFIG_SYS_FSL_SEC_ADDR + 0x1108 + y*16)
> +#define CAAM_SMAG1JR0(y)       (CONFIG_SYS_FSL_SEC_ADDR + 0x110C + y*16)

Comments for these?

> +
> +#define ERROR_IN_PAGE_ALLOC    (1)

Remove (). Also can you use something from errno.h?

> +#define CMD_PAGE_ALLOC         0x1
> +#define CMD_PAGE_DEALLOC       0x2
> +#define CMD_PART_DEALLOC       0x3
> +#define CMD_INQUIRY            0x5
> +#define CMD_COMPLETE           (3 << 14)
> +#define PAGE_AVAILABLE         0
> +#define PAGE_OWNED             (3 << 6)
> +#define PAGE(x)                        (x << 16)
> +#define PARTITION(x)           (x << 8)
> +#define PARTITION_OWNER(x)     (0x3 << (x*2))
> +
> +/* 4kbyte pages */
> +#define SEC_MEM_PAGE0          CAAM_ARB_BASE_ADDR
> +#define SEC_MEM_PAGE1          (CAAM_ARB_BASE_ADDR + 0x1000)
> +#define SEC_MEM_PAGE2          (CAAM_ARB_BASE_ADDR + 0x2000)
> +#define SEC_MEM_PAGE3          (CAAM_ARB_BASE_ADDR + 0x3000)
> +
> +#define JR_MID                 2               /* Matches ROM configuration */
> +#define KS_G1                  (1 << JR_MID)   /* CAAM only */
> +#define PERM                   0x0000B008      /* Clear on release, lock SMAP
> +                                                * lock SMAG group 1 Blob */
> +
> +/* HAB WRAPPED KEY header */
> +#define WRP_HDR_SIZE           0x08
> +#define HDR_TAG                        0x81
> +#define HDR_PAR                        0x41
> +/* HAB WRAPPED KEY Data */
> +#define HAB_MOD                        0x66
> +#define HAB_ALG                        0x55
> +#define HAB_FLG                        0x00
> +
> +#define PARTITION_1            1
> +#define PAGE_1                 1

What are these two?

> +
> +#endif
> +
>  int sec_init(void);
> +
> +int blob_dek(u8 *src, u8 *dst, u8 len);

Function comments

> +
>  #endif
>
>  #endif /* __FSL_SEC_H */
> --
> 1.7.9.5
>

Regards,
Simon
diff mbox

Patch

diff --git a/arch/arm/imx-common/Makefile b/arch/arm/imx-common/Makefile
index 25a9d4c..606482f 100644
--- a/arch/arm/imx-common/Makefile
+++ b/arch/arm/imx-common/Makefile
@@ -24,6 +24,7 @@  obj-$(CONFIG_IMX_VIDEO_SKIP) += video.o
 endif
 obj-$(CONFIG_CMD_BMODE) += cmd_bmode.o
 obj-$(CONFIG_CMD_HDMIDETECT) += cmd_hdmidet.o
+obj-$(CONFIG_CMD_DEKBLOB) += cmd_dek.o
 
 quiet_cmd_cpp_cfg = CFGS    $@
       cmd_cpp_cfg = $(CPP) $(cpp_flags) -x c -o $@ $<
diff --git a/arch/arm/imx-common/cmd_dek.c b/arch/arm/imx-common/cmd_dek.c
new file mode 100644
index 0000000..1a3a996a
--- /dev/null
+++ b/arch/arm/imx-common/cmd_dek.c
@@ -0,0 +1,89 @@ 
+/*
+ * Command for encapsulating DEK blob
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <environment.h>
+#include <malloc.h>
+#include <asm/byteorder.h>
+#include <linux/compiler.h>
+#include <fsl_sec.h>
+#include <asm/arch/clock.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+* blob_dek() - Encapsulate the DEK as a blob using CAM's Key
+* @src: - Address of data to be encapsulated
+* @dst: - Address of data to be encapsulated
+* @len: - Size of data to be encapsulated
+*
+* Returns zero on success,and negative on error.
+*/
+static int blob_encap_dek(u8 *src, u8 *dst, u32 len)
+{
+	int ret = 0;
+	u32 jr_size = 4;
+
+	u32 out_jr_size = sec_in32(CONFIG_SYS_FSL_JR0_ADDR + 0x102c);
+	if (out_jr_size != jr_size) {
+		hab_caam_clock_enable(1);
+		sec_init();
+	}
+
+	if (!((len == 128)|(len == 192)|(len == 256))) {
+		debug("Invalid DEK size. Valid sizes are 128, 192 and 256b\n");
+		return -1;
+	}
+
+	len /= 8;
+	ret = blob_dek(src, dst, len);
+
+	return ret;
+}
+
+/**
+ * do_dek_blob() - Handle the "dek_blob" command-line command
+ * @cmdtp:  Command data struct pointer
+ * @flag:   Command flag
+ * @argc:   Command-line argument count
+ * @argv:   Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
+static int do_dek_blob(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	uint32_t src_addr, dst_addr, len;
+	uint8_t *src_ptr, *dst_ptr;
+	int ret = 0;
+
+	if (argc != 4)
+		return CMD_RET_USAGE;
+
+	src_addr = simple_strtoul(argv[1], NULL, 16);
+	dst_addr = simple_strtoul(argv[2], NULL, 16);
+	len = simple_strtoul(argv[3], NULL, 10);
+
+	src_ptr = (uint8_t *)src_addr;
+	dst_ptr = (uint8_t *)dst_addr;
+
+	ret = blob_encap_dek(src_ptr, dst_ptr, len);
+
+	return ret;
+}
+
+/***************************************************/
+static char dek_blob_help_text[] =
+	"src dst len            - Encapsulate and create blob of data\n"
+	"                         $len bits long at address $src and\n"
+	"                         store the result at address $dst.\n";
+
+U_BOOT_CMD(
+	dek_blob, 4, 1, do_dek_blob,
+	"Data Encryption Key blob encapsulation",
+	dek_blob_help_text
+);
diff --git a/arch/arm/imx-common/timer.c b/arch/arm/imx-common/timer.c
index 65ef60b..e522990 100644
--- a/arch/arm/imx-common/timer.c
+++ b/arch/arm/imx-common/timer.c
@@ -176,3 +176,20 @@  ulong get_tbclk(void)
 {
 	return gpt_get_clk();
 }
+
+/*
+ * This function is intended for SHORT delays only.
+ * It will overflow at around 10 seconds @ 400MHz,
+ * or 20 seconds @ 200MHz.
+ */
+unsigned long usec2ticks(unsigned long usec)
+{
+	ulong ticks;
+
+	if (usec < 1000)
+		ticks = ((usec * (get_tbclk()/1000)) + 500) / 1000;
+	else
+		ticks = ((usec / 10) * (get_tbclk() / 100000));
+
+	return ticks;
+}
diff --git a/arch/arm/include/asm/arch-mx6/imx-regs.h b/arch/arm/include/asm/arch-mx6/imx-regs.h
index ae88b6e..065b27b 100644
--- a/arch/arm/include/asm/arch-mx6/imx-regs.h
+++ b/arch/arm/include/asm/arch-mx6/imx-regs.h
@@ -215,6 +215,10 @@ 
 #define AIPS2_OFF_BASE_ADDR         (ATZ2_BASE_ADDR + 0x80000)
 #define CAAM_BASE_ADDR              (ATZ2_BASE_ADDR)
 #define ARM_BASE_ADDR		    (ATZ2_BASE_ADDR + 0x40000)
+
+#define CONFIG_SYS_FSL_SEC_ADDR     (CAAM_BASE_ADDR)
+#define CONFIG_SYS_FSL_JR0_ADDR     (CAAM_BASE_ADDR + 0x1000)
+
 #define USB_PL301_BASE_ADDR         (AIPS2_OFF_BASE_ADDR + 0x0000)
 #define USB_BASE_ADDR               (AIPS2_OFF_BASE_ADDR + 0x4000)
 
diff --git a/doc/README.mxc_hab b/doc/README.mxc_hab
index 43e64a2..46ed0df 100644
--- a/doc/README.mxc_hab
+++ b/doc/README.mxc_hab
@@ -46,3 +46,51 @@  cat u-boot.imx U-Boot_CSF_pad.bin > u-boot-signed.imx
 
 NOTE: U-Boot_CSF.bin needs to be padded to the value specified in
 the imximage.cfg file.
+
+Setup U-Boot Image for Encrypted Boot
+-------------------------------------
+An authenticated  U-boot image  is used as starting point for
+Encrypted Boot. The image is encrypted by Freescale's Code
+Signing Tool (CST). The CST replaces only the image data of
+u-boot.imx with the encrypted data. The Initial Vector Table,
+DCD, and Boot data, remains in plaintext.
+
+The image data  is encrypted with a Encryption Key (DEK).
+Therefore, this key is needed to decrypt the data during the
+booting process. The DEK is protected by wrapping it in a Blob,
+which needs to be appended to the U-boot image and specified in
+the CSF file.
+
+The DEK blob is generated by an authenticated U-boot image with
+the dek_blob cmd enabled. The image used for DEK blob generation
+needs to have the following configurations enabled:
+
+CONFIG_SECURE_BOOT
+CONFIG_SYS_FSL_SEC_COMPAT    4 /* HAB version */
+CONFIG_FSL_CAAM
+CONFIG_CMD_DEKBLOB
+
+Note: The encrypted boot feature is only supported by HABv4 or
+greater.
+
+The dek_blob command then can be used to generate the DEK blob of
+a DEK previously loaded in memory. The command is used as follows:
+
+dek_blob <DEK address>  <Output Address> <Key Size in Bits>
+example:  dek_blob 0x10800000 0x10801000 192
+
+The resulting DEK blob then is used to construct the encrypted
+U-boot image. Note that the blob needs to be transfered back
+to the host.Then the following commands are used to construct
+the final image.
+
+objcopy -I binary -O binary --pad-to 0x2000 --gap-fill=0x00 \
+    U-Boot_CSF.bin U-Boot_CSF_pad.bin
+cat u-boot.imx U-Boot_CSF_pad.bin > u-boot-signed.imx
+objcopy -I binary -O binary --pad-to <blob_dst> --gap-fill=0x00 \
+    u-boot-signed.imx u-boot-signed-pad.bin
+cat u-boot-signed-pad.imx DEK_blob.bin > u-boot-encrypted.imx
+
+    NOTE: u-boot-signed.bin needs to be padded to the value
+    equivalent to the address in which the DEK blob is specified
+    in the CSF.
diff --git a/drivers/crypto/fsl/Makefile b/drivers/crypto/fsl/Makefile
index c0cf642..4aa91e4 100644
--- a/drivers/crypto/fsl/Makefile
+++ b/drivers/crypto/fsl/Makefile
@@ -8,5 +8,5 @@ 
 
 obj-y += sec.o
 obj-$(CONFIG_FSL_CAAM) += jr.o fsl_hash.o jobdesc.o error.o
-obj-$(CONFIG_CMD_BLOB) += fsl_blob.o
+obj-$(CONFIG_CMD_BLOB)$(CONFIG_CMD_DEKBLOB) += fsl_blob.o
 obj-$(CONFIG_RSA_FREESCALE_EXP) += fsl_rsa.o
diff --git a/drivers/crypto/fsl/desc.h b/drivers/crypto/fsl/desc.h
index 504f2b0..bb82734 100644
--- a/drivers/crypto/fsl/desc.h
+++ b/drivers/crypto/fsl/desc.h
@@ -12,11 +12,18 @@ 
 #ifndef DESC_H
 #define DESC_H
 
+#define KEY_BLOB_SIZE		32
+#define MAC_SIZE		16
+
 /* Max size of any CAAM descriptor in 32-bit words, inclusive of header */
 #define MAX_CAAM_DESCSIZE	64
 
+/* Size of DEK Blob  descriptor, inclusive of header */
+#define DEK_BLOB_DESCSIZE	9
+
 /* Block size of any entity covered/uncovered with a KEK/TKEK */
 #define KEK_BLOCKSIZE		16
+
 /*
  * Supported descriptor command types as they show up
  * inside a descriptor command word.
@@ -273,6 +280,13 @@ 
 #define LDLEN_SET_OFIFO_OFFSET_MASK	(3 << LDLEN_SET_OFIFO_OFFSET_SHIFT)
 
 /*
+ * AAD Definitions
+ */
+#define AES_KEY_SHIFT		8
+#define LD_CCM_MODE		(0x66)
+#define KEY_AES_SRC		(0x55 << AES_KEY_SHIFT)
+
+/*
  * FIFO_LOAD/FIFO_STORE/SEQ_FIFO_LOAD/SEQ_FIFO_STORE
  * Command Constructs
  */
@@ -418,6 +432,7 @@ 
 #define OP_PCLID_MASK		(0xff << 16)
 
 /* Assuming OP_TYPE = OP_TYPE_UNI_PROTOCOL */
+#define OP_PCLID_SECMEM		(0x08)
 #define OP_PCLID_BLOB		(0x0d << OP_PCLID_SHIFT)
 #define OP_PCLID_SECRETKEY	(0x11 << OP_PCLID_SHIFT)
 #define OP_PCLID_PUBLICKEYPAIR	(0x14 << OP_PCLID_SHIFT)
diff --git a/drivers/crypto/fsl/fsl_blob.c b/drivers/crypto/fsl/fsl_blob.c
index bc01075..f9dc85a 100644
--- a/drivers/crypto/fsl/fsl_blob.c
+++ b/drivers/crypto/fsl/fsl_blob.c
@@ -7,6 +7,7 @@ 
 
 #include <common.h>
 #include <malloc.h>
+#include <fsl_sec.h>
 #include "jobdesc.h"
 #include "desc.h"
 #include "jr.h"
@@ -59,3 +60,52 @@  int blob_encrypt(u8 *key_mod, u8 *src, u8 *dst, u8 len)
 	free(desc);
 	return ret;
 }
+
+#ifdef CONFIG_CMD_DEKBLOB
+int blob_dek(u8 *src, u8 *dst, u8 len)
+{
+	int ret, size, i = 0;
+	u32 *desc;
+
+	int out_sz =  WRP_HDR_SIZE + len + KEY_BLOB_SIZE + MAC_SIZE;
+
+	puts("\nEncapsulating provided DEK to form blob\n");
+	desc = memalign(ARCH_DMA_MINALIGN,
+			sizeof(uint32_t) * DEK_BLOB_DESCSIZE);
+	if (!desc) {
+		debug("Not enough memory for descriptor allocation\n");
+		return -1;
+	}
+
+	ret = inline_cnstr_jobdesc_blob_dek(desc, src, dst, len);
+	if (ret) {
+		debug("Error in Job Descriptor Construction:  %d\n", ret);
+	} else {
+		size = roundup(sizeof(uint32_t) * DEK_BLOB_DESCSIZE,
+			      ARCH_DMA_MINALIGN);
+		flush_dcache_range((unsigned long)desc,
+				   (unsigned long)desc + size);
+		size = roundup(sizeof(uint8_t) * out_sz, ARCH_DMA_MINALIGN);
+		flush_dcache_range((unsigned long)dst,
+				   (unsigned long)dst + size);
+
+		ret = run_descriptor_jr(desc);
+	}
+
+	if (ret)
+		debug("Error in Encapsulation %d\n", ret);
+
+	size = roundup(out_sz, ARCH_DMA_MINALIGN);
+	invalidate_dcache_range((unsigned long)dst, (unsigned long)dst+size);
+
+	/* Print DEK Blob */
+	puts("DEK Blob\n");
+	for (i = 0; i < out_sz; i++)
+		printf("%02X", ((uint8_t *)dst)[i]);
+
+	puts("\n\n");
+
+	free(desc);
+	return ret;
+}
+#endif
diff --git a/drivers/crypto/fsl/jobdesc.c b/drivers/crypto/fsl/jobdesc.c
index cc0dced..4dc73ae 100644
--- a/drivers/crypto/fsl/jobdesc.c
+++ b/drivers/crypto/fsl/jobdesc.c
@@ -9,12 +9,150 @@ 
  */
 
 #include <common.h>
+#include <fsl_sec.h>
 #include "desc_constr.h"
 #include "jobdesc.h"
 #include "rsa_caam.h"
 
-#define KEY_BLOB_SIZE			32
-#define MAC_SIZE			16
+#ifdef CONFIG_MX6
+/*!
+ * Secure memory run command.
+ *
+ * @param   sec_mem_cmd  Secure memory command register
+ * @return  cmd_status  Secure memory command status register
+ */
+uint32_t secmem_set_cmd(uint32_t sec_mem_cmd)
+{
+	uint32_t temp_reg;
+
+	sec_out32(CAAM_SMCJR0, sec_mem_cmd);
+
+	do {
+		temp_reg = sec_in32(CAAM_SMCSJR0);
+	} while (temp_reg & CMD_COMPLETE);
+
+	return temp_reg;
+}
+
+/*!
+ * CAAM page allocation.
+ *
+ * @param   page  Number of the page to allocate.
+ * @param   partition  Number of the partition to allocate.
+ */
+uint32_t caam_page_alloc(uint8_t page_num, uint8_t partition_num)
+{
+	uint32_t temp_reg;
+
+	/*
+	 * De-Allocate partition_num if already allocated to ARM core
+	 */
+	if (sec_in32(CAAM_SMPO_0) & PARTITION_OWNER(partition_num)) {
+		temp_reg = secmem_set_cmd(PARTITION(partition_num) |
+						CMD_PART_DEALLOC);
+		if (temp_reg & SMCSJR_AERR) {
+			printf("Error: De-allocation status 0x%X\n", temp_reg);
+			return ERROR_IN_PAGE_ALLOC;
+		}
+	}
+
+	/* set the access rights to allow full access */
+	sec_out32(CAAM_SMAG1JR0(partition_num), 0xF);
+	sec_out32(CAAM_SMAG2JR0(partition_num), 0xF);
+	sec_out32(CAAM_SMAPJR0(partition_num), 0xFF);
+
+	/* Now need to allocate partition_num of secure RAM. */
+	/* De-Allocate page_num by starting with a page inquiry command */
+	temp_reg = secmem_set_cmd(PAGE(page_num) | CMD_INQUIRY);
+
+	/* if the page is owned, de-allocate it */
+	if ((temp_reg & SMCSJR_PO) == PAGE_OWNED) {
+		temp_reg = secmem_set_cmd(PAGE(page_num) | CMD_PAGE_DEALLOC);
+		if (temp_reg & SMCSJR_AERR) {
+			printf("Error: Allocation status 0x%X\n", temp_reg);
+			return ERROR_IN_PAGE_ALLOC;
+		}
+	}
+
+	/* Allocate page_num to partition_num */
+	temp_reg = secmem_set_cmd(PAGE(page_num) | PARTITION(partition_num)
+						| CMD_PAGE_ALLOC);
+	if (temp_reg & SMCSJR_AERR) {
+		printf("Error: Allocation status 0x%X\n", temp_reg);
+		return ERROR_IN_PAGE_ALLOC;
+	}
+	/* page inquiry command to ensure that the page was allocated */
+	temp_reg = secmem_set_cmd(PAGE(page_num) | CMD_INQUIRY);
+
+	/* if the page is not owned => problem */
+	if ((temp_reg & SMCSJR_PO) != PAGE_OWNED) {
+		printf("Allocation of page %d in partition %d failed 0x%X\n",
+		       temp_reg, page_num, partition_num);
+
+		return ERROR_IN_PAGE_ALLOC;
+	}
+
+	return 0;
+}
+
+uint32_t inline_cnstr_jobdesc_blob_dek(uint32_t *desc, uint8_t *plain_txt,
+				       uint8_t *dek_blob, uint32_t in_sz)
+{
+	uint32_t ret = 0;
+	u32 aad_w1, aad_w2;
+	/* output blob will have 32 bytes key blob in beginning and
+	 * 16 byte HMAC identifier at end of data blob */
+	uint32_t out_sz = in_sz + KEY_BLOB_SIZE + MAC_SIZE;
+	/* Setting HDR for blob */
+	uint8_t wrapped_key_hdr[8] = {HDR_TAG, 0x00, WRP_HDR_SIZE + out_sz,
+				     HDR_PAR, HAB_MOD, HAB_ALG, in_sz, HAB_FLG};
+
+	/* initialize the blob array */
+	memset(dek_blob, 0, out_sz + 8);
+	/* Copy the header into the DEK blob buffer */
+	memcpy((uint32_t *)dek_blob, wrapped_key_hdr, sizeof(wrapped_key_hdr));
+
+	/* allocating secure memory */
+	ret = caam_page_alloc(PAGE_1, PARTITION_1);
+	if (ret)
+		return ret;
+
+	/* Write DEK to secure memory */
+	memcpy((uint32_t *)SEC_MEM_PAGE1, (uint32_t *)plain_txt, in_sz);
+
+	unsigned long start = (unsigned long)SEC_MEM_PAGE1 &
+				~(ARCH_DMA_MINALIGN - 1);
+	unsigned long end = ALIGN(start + 0x1000, ARCH_DMA_MINALIGN);
+	flush_dcache_range(start, end);
+
+	/* Now configure the access rights of the partition */
+	sec_out32(CAAM_SMAG1JR0(PARTITION_1), KS_G1); /* set group 1 */
+	sec_out32(CAAM_SMAG2JR0(PARTITION_1), 0);     /* clear group 2 */
+	sec_out32(CAAM_SMAPJR0(PARTITION_1), PERM);   /* set perm & locks */
+
+	/* construct aad for AES */
+	aad_w1 = (in_sz << OP_ALG_ALGSEL_SHIFT) | KEY_AES_SRC | LD_CCM_MODE;
+	aad_w2 = 0x0;
+
+	init_job_desc(desc, 0);
+
+	append_cmd(desc, CMD_LOAD | CLASS_2 | KEY_IMM | KEY_ENC |
+				(0x0c << LDST_OFFSET_SHIFT) | 0x08);
+
+	append_u32(desc, aad_w1);
+
+	append_u32(desc, aad_w2);
+
+	append_cmd_ptr(desc, (dma_addr_t)SEC_MEM_PAGE1, in_sz, CMD_SEQ_IN_PTR);
+
+	append_cmd_ptr(desc, (dma_addr_t)dek_blob + 8, out_sz, CMD_SEQ_OUT_PTR);
+
+	append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB |
+						OP_PCLID_SECMEM);
+
+	return ret;
+}
+#endif
 
 void inline_cnstr_jobdesc_hash(uint32_t *desc,
 			  const uint8_t *msg, uint32_t msgsz, uint8_t *digest,
diff --git a/drivers/crypto/fsl/jobdesc.h b/drivers/crypto/fsl/jobdesc.h
index 84b3edd..d20c18c 100644
--- a/drivers/crypto/fsl/jobdesc.h
+++ b/drivers/crypto/fsl/jobdesc.h
@@ -14,6 +14,11 @@ 
 
 #define KEY_IDNFR_SZ_BYTES		16
 
+#ifdef CONFIG_CMD_DEKBLOB
+uint32_t inline_cnstr_jobdesc_blob_dek(uint32_t *desc, uint8_t *plain_txt,
+				uint8_t *enc_blob, uint32_t in_sz);
+#endif
+
 void inline_cnstr_jobdesc_hash(uint32_t *desc,
 			  const uint8_t *msg, uint32_t msgsz, uint8_t *digest,
 			  u32 alg_type, uint32_t alg_size, int sg_tbl);
diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c
index f9d4938..f99d594 100644
--- a/drivers/crypto/fsl/jr.c
+++ b/drivers/crypto/fsl/jr.c
@@ -90,11 +90,13 @@  static int jr_init(void)
 	jr.liodn = DEFAULT_JR_LIODN;
 #endif
 	jr.size = JR_SIZE;
-	jr.input_ring = (dma_addr_t *)malloc(JR_SIZE * sizeof(dma_addr_t));
+	jr.input_ring = (dma_addr_t *)memalign(ARCH_DMA_MINALIGN,
+				JR_SIZE * sizeof(dma_addr_t));
 	if (!jr.input_ring)
 		return -1;
 	jr.output_ring =
-	    (struct op_ring *)malloc(JR_SIZE * sizeof(struct op_ring));
+	    (struct op_ring *)memalign(ARCH_DMA_MINALIGN,
+				JR_SIZE * sizeof(struct op_ring));
 	if (!jr.output_ring)
 		return -1;
 
@@ -163,13 +165,23 @@  static int jr_enqueue(uint32_t *desc_addr,
 	    CIRC_SPACE(jr.head, jr.tail, jr.size) <= 0)
 		return -1;
 
-	jr.input_ring[head] = desc_phys_addr;
 	jr.info[head].desc_phys_addr = desc_phys_addr;
 	jr.info[head].desc_addr = (uint32_t)desc_addr;
 	jr.info[head].callback = (void *)callback;
 	jr.info[head].arg = arg;
 	jr.info[head].op_done = 0;
 
+	unsigned long start = (unsigned long)&jr.info[head] &
+					~(ARCH_DMA_MINALIGN - 1);
+	unsigned long end = ALIGN(start + sizeof(struct jr_info),
+					ARCH_DMA_MINALIGN);
+	flush_dcache_range(start, end);
+
+	jr.input_ring[head] = desc_phys_addr;
+	start = (unsigned long)&jr.input_ring[head] & ~(ARCH_DMA_MINALIGN - 1);
+	end = ALIGN(start + sizeof(dma_addr_t), ARCH_DMA_MINALIGN);
+	flush_dcache_range(start, end);
+
 	jr.head = (head + 1) & (jr.size - 1);
 
 	sec_out32(&regs->irja, 1);
@@ -187,6 +199,13 @@  static int jr_dequeue(void)
 	void *arg = NULL;
 
 	while (sec_in32(&regs->orsf) && CIRC_CNT(jr.head, jr.tail, jr.size)) {
+		unsigned long start = (unsigned long)jr.output_ring &
+					~(ARCH_DMA_MINALIGN - 1);
+		unsigned long end = ALIGN(start +
+					  sizeof(struct op_ring)*JR_SIZE,
+					  ARCH_DMA_MINALIGN);
+		invalidate_dcache_range(start, end);
+
 		found = 0;
 
 		dma_addr_t op_desc = jr.output_ring[jr.tail].desc;
@@ -333,13 +352,17 @@  static int instantiate_rng(void)
 
 	memset(&op, 0, sizeof(struct result));
 
-	desc = malloc(sizeof(int) * 6);
+	desc = memalign(ARCH_DMA_MINALIGN, sizeof(uint32_t) * 6);
 	if (!desc) {
 		printf("cannot allocate RNG init descriptor memory\n");
 		return -1;
 	}
 
 	inline_cnstr_jobdesc_rng_instantiation(desc);
+	int size = roundup(sizeof(uint32_t) * 6, ARCH_DMA_MINALIGN);
+	flush_dcache_range((unsigned long)desc,
+			   (unsigned long)desc + size);
+
 	ret = run_descriptor_jr(desc);
 
 	if (ret)
diff --git a/include/fsl_sec.h b/include/fsl_sec.h
index aa850a3..95fbb6b 100644
--- a/include/fsl_sec.h
+++ b/include/fsl_sec.h
@@ -11,6 +11,13 @@ 
 #include <common.h>
 #include <asm/io.h>
 
+#ifdef CONFIG_ARM
+#define sec_in32(a)       __raw_readl(a)
+#define sec_out32(a, v)   __raw_writel(v, a)
+#define sec_in16(a)       __raw_readw(a)
+#define sec_clrbits32     clrbits_le32
+#define sec_setbits32     setbits_le32
+#elif CONFIG_PPC
 #ifdef CONFIG_SYS_FSL_SEC_LE
 #define sec_in32(a)       in_le32(a)
 #define sec_out32(a, v)   out_le32(a, v)
@@ -26,6 +33,7 @@ 
 #else
 #error Neither CONFIG_SYS_FSL_SEC_LE nor CONFIG_SYS_FSL_SEC_BE is defined
 #endif
+#endif      /* ARCHITECURE */
 
 /* Security Engine Block (MS = Most Sig., LS = Least Sig.) */
 #if CONFIG_SYS_FSL_SEC_COMPAT >= 4
@@ -175,7 +183,59 @@  struct jr_regs {
 	u32 jrcr;
 };
 
+#ifdef CONFIG_MX6
+
+#define SMCSJR_PO		(3 << 6)
+#define SMCSJR_AERR		(3 << 12)
+#define SMCSJR_CERR		(3 << 14)
+#define CAAM_SMPO_0		CONFIG_SYS_FSL_SEC_ADDR + 0x1FBC
+#define CAAM_SMCJR0		CONFIG_SYS_FSL_SEC_ADDR + 0x10f4
+#define CAAM_SMCSJR0		CONFIG_SYS_FSL_SEC_ADDR + 0x10fc
+#define CAAM_SMAPJR0(y)		(CONFIG_SYS_FSL_SEC_ADDR + 0x1104 + y*16)
+#define CAAM_SMAG2JR0(y)	(CONFIG_SYS_FSL_SEC_ADDR + 0x1108 + y*16)
+#define CAAM_SMAG1JR0(y)	(CONFIG_SYS_FSL_SEC_ADDR + 0x110C + y*16)
+
+#define ERROR_IN_PAGE_ALLOC	(1)
+#define CMD_PAGE_ALLOC		0x1
+#define CMD_PAGE_DEALLOC	0x2
+#define CMD_PART_DEALLOC	0x3
+#define CMD_INQUIRY		0x5
+#define CMD_COMPLETE		(3 << 14)
+#define PAGE_AVAILABLE		0
+#define PAGE_OWNED		(3 << 6)
+#define PAGE(x)			(x << 16)
+#define PARTITION(x)		(x << 8)
+#define PARTITION_OWNER(x)	(0x3 << (x*2))
+
+/* 4kbyte pages */
+#define SEC_MEM_PAGE0		CAAM_ARB_BASE_ADDR
+#define SEC_MEM_PAGE1		(CAAM_ARB_BASE_ADDR + 0x1000)
+#define SEC_MEM_PAGE2		(CAAM_ARB_BASE_ADDR + 0x2000)
+#define SEC_MEM_PAGE3		(CAAM_ARB_BASE_ADDR + 0x3000)
+
+#define JR_MID			2               /* Matches ROM configuration */
+#define KS_G1			(1 << JR_MID)   /* CAAM only */
+#define PERM			0x0000B008      /* Clear on release, lock SMAP
+						 * lock SMAG group 1 Blob */
+
+/* HAB WRAPPED KEY header */
+#define WRP_HDR_SIZE		0x08
+#define HDR_TAG			0x81
+#define HDR_PAR			0x41
+/* HAB WRAPPED KEY Data */
+#define HAB_MOD			0x66
+#define HAB_ALG			0x55
+#define HAB_FLG			0x00
+
+#define PARTITION_1		1
+#define PAGE_1			1
+
+#endif
+
 int sec_init(void);
+
+int blob_dek(u8 *src, u8 *dst, u8 len);
+
 #endif
 
 #endif /* __FSL_SEC_H */