AnsweredAssumed Answered

How do you properly setup a CAAM job to perform en/de-capsulation of generic data (not secure memory keys)?

Question asked by awright on Sep 26, 2013
Latest reply on May 11, 2017 by Jose Diaz de Grenu de Pedro

I am trying to use the feature of the i.MX6 processor to perform generic protection of data for secure storage in non-volatile memory. This is done by having the i.MX6 convert the data into a red blob (for general data). I found what I believe is a similar question from user fsquestion at  This question is marked as "Assumed Answered", but it was not.  The only response is from Freescale, but is a response about Encrypted Boot (a completely separate topic). fsquestion has posted that they have still not figured out a way to do this, as current examples are limited to using the secure memory operations. This question does not deal with encrypted boot, just the handling en/de-capsulation of red blobs.




I am attempting to wire a Linux driver to present a character interface that provides an IOCTL to allow user space applications to have a synchronous method to provide data to be en/de-capsulated into/out of red blobs and get the result. I am getting an error from the CAAM job, which tells me that something is wrong with the job descriptor:



0x04 0x00 0x00 0x00 0x0008   0x0010

                    DESC IDX ERR: Inv. Seq Command


I tried to build up the descriptor using the following function, which is based on blob_encap_desc in sm_store.c, but modified to attempt to make red blobs to/from regular memory (not secure memory). I have not been able to figure out how to modify (or build) a proper CAAM job descriptor to perform the red blob en/de-capsulation.



* Construct a in-memory red blob en/de-capsulation job descriptor


* - desc pointer to hold new (to be allocated) pointer to the generated

* descriptor for later use. Calling thread can kfree the

* descriptor after execution.

* - keymod Physical pointer to key modifier (contiguous piece).

* - keymodsz Size of key modifier in bytes (should normally be 8).

* - inbuf Physical pointer of the data to be en/de-capsulated.

* - outbuf Physical pointer (within an accessible secure memory page)

* of the encapsulated output. This needs to be larger than the

* input buffer by 48 bytes when performing encapsulation of the data.

* - inbuflen Size of input buffer, in bytes.

* - auth If nonzero, use AES-CCM for encapsulation, else use ECB


* Note: this uses 32-bit pointers at present

* retval: number of bytes in outbuf


#define INITIAL_DESCSZ 16 /* size of tmp buffer for descriptor const. */

static int caam_blob_capsulate_desc(u32 **desc, dma_addr_t keymod, u16 keymodsz,

  bool encap, dma_addr_t inbuf, dma_addr_t outbuf, u16 inbuflen,

  bool auth)


  u32 *tdesc, tmpdesc[INITIAL_DESCSZ];

  u16 dsize, idx;


  memset(tmpdesc, 0, INITIAL_DESCSZ * sizeof(u32));

  idx = 1;


  /* Load key modifier */



  (keymodsz & LDST_LEN_MASK);


  tmpdesc[idx++] = (u32)keymod;


  if(encap) {

  /* Encapsulate to memory */

  tmpdesc[idx++] = CMD_SEQ_IN_PTR | inbuflen;

  tmpdesc[idx++] = (u32)inbuf;



  /* Compensate for BKEK and MAC tag */

  tmpdesc[idx++] = CMD_SEQ_IN_PTR | (inbuflen + CAAM_BLOB_HDR_SIZE);


  if(encap) {

  /* Encapsulate to memory */

  tmpdesc[idx++] = (u32)outbuf;

  } else {

  tmpdesc[idx++] = (u32)inbuf;

  tmpdesc[idx++] = CMD_SEQ_OUT_PTR | inbuflen;

  tmpdesc[idx++] = (u32)outbuf;





  /* En/De-capsulate to memory */




  if (auth)

  tmpdesc[idx] |= OP_PCL_BLOB_EKT;



  tmpdesc[0] = CMD_DESC_HDR | HDR_ONE | (idx & HDR_DESCLEN_MASK);

  dsize = idx * sizeof(u32);


  tdesc = kmalloc(dsize, GFP_KERNEL | GFP_DMA);

  if (tdesc == NULL)

  return 0;


  memcpy(tdesc, tmpdesc, dsize);

  *desc = tdesc;

  return dsize;