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 https://community.freescale.com/message/340700.  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:

 

1073743888

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 */

  tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY |

  ((12 << LDST_OFFSET_SHIFT) & LDST_OFFSET_MASK) |

  (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;

 

  tmpdesc[idx] = CMD_OPERATION | OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB |

      OP_PCL_BLOB_FMT_NORMAL;

  }

  /* En/De-capsulate to memory */

  tmpdesc[idx] = CMD_OPERATION | OP_PCLID_BLOB | OP_PCL_BLOB_FMT_NORMAL |

  (encap?OP_TYPE_ENCAP_PROTOCOL:OP_TYPE_DECAP_PROTOCOL);

 

  if (auth)

  tmpdesc[idx] |= OP_PCL_BLOB_EKT;

 

  idx++;

  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;

}

Outcomes