Logo Search packages:      
Sourcecode: linux-fsl-imx51 version File versions  Download package

scc_return_t scc_encrypt_region ( uint32_t  part_base,
uint32_t  offset_bytes,
uint32_t  byte_count,
uint8_t *  black_data,
uint32_t *  IV,
scc_cypher_mode_t  cypher_mode 
)

Encrypt a region of secure memory.

Parameters:
part_base Kernel virtual address of the partition.
offset_bytes Offset from the start of the partition to the plaintext data.
byte_count Length of the region (octets).
black_data Physical location to store the encrypted data.
IV Value to use for the IV.
cypher_mode Cyphering mode to use, specified by type scc_cypher_mode_t
Returns:
SCC_RET_OK if successful.

Definition at line 1345 of file scc2_driver.c.

References os_lock_save_context, os_unlock_restore_context, SCC_BLOCK_SIZE_BYTES, scc_crypto_lock, SCC_CYPHER_MODE_CBC, SCC_CYPHER_MODE_ECB, scc_do_crypto(), SCC_RET_FAIL, SCC_RET_OK, SCC_WRITE_REGISTER, SCM_AES_CBC_IV0_REG, SCM_AES_CBC_IV1_REG, SCM_AES_CBC_IV2_REG, SCM_AES_CBC_IV3_REG, SCM_C_BLACK_ST_REG, SCM_CCMD_AES_ENC_CBC, SCM_CCMD_AES_ENC_ECB, SCM_CCMD_OFFSET_SHIFT, SCM_CCMD_PART_SHIFT, and SCM_PART_NUMBER.

Referenced by do_scc_encrypt_region().

{
      os_lock_context_t irq_flags;  /* for IRQ save/restore */
      scc_return_t status = SCC_RET_OK;
      uint32_t crypto_status;
      uint32_t scm_command;
      int offset_blocks = offset_bytes / SCC_BLOCK_SIZE_BYTES();

#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18))
                        mxc_clks_enable(SCC_CLK);
#else
                        if (scc_clk != ERR_PTR(ENOENT))
                              clk_enable(scc_clk);
#endif

      scm_command = ((offset_blocks << SCM_CCMD_OFFSET_SHIFT) |
                   (SCM_PART_NUMBER(part_base) << SCM_CCMD_PART_SHIFT));

      switch (cypher_mode) {
      case SCC_CYPHER_MODE_CBC:
            scm_command |= SCM_CCMD_AES_ENC_CBC;
            break;
      case SCC_CYPHER_MODE_ECB:
            scm_command |= SCM_CCMD_AES_ENC_ECB;
            break;
      default:
            status = SCC_RET_FAIL;
            break;
      }

      pr_debug("Received encrypt request.  SCM_C_BLACK_ST_REG: %p, "
             "scm_Command: %08x, length: %i (part_base: %08x, "
             "offset: %i)\n",
             black_data, scm_command, byte_count, part_base, offset_blocks);

      if (status != SCC_RET_OK)
            goto out;

      /* ACQUIRE LOCK to prevent others from using crypto or releasing slot */
      os_lock_save_context(scc_crypto_lock, irq_flags);

      if (status == SCC_RET_OK) {
            SCC_WRITE_REGISTER(SCM_C_BLACK_ST_REG, (uint32_t) black_data);

            /* Only write the IV if it will actually be used */
            if (cypher_mode == SCC_CYPHER_MODE_CBC) {
                  /* Write the IV register */
                  SCC_WRITE_REGISTER(SCM_AES_CBC_IV0_REG, *(IV));
                  SCC_WRITE_REGISTER(SCM_AES_CBC_IV1_REG, *(IV + 1));
                  SCC_WRITE_REGISTER(SCM_AES_CBC_IV2_REG, *(IV + 2));
                  SCC_WRITE_REGISTER(SCM_AES_CBC_IV3_REG, *(IV + 3));
            }

            /* Set modes and kick off the encryption */
            crypto_status = scc_do_crypto(byte_count, scm_command);

            if (crypto_status != 0) {
                  pr_debug("SCM encrypt red crypto failure: 0x%x\n",
                         crypto_status);
            } else {
                  status = SCC_RET_OK;
                  pr_debug("SCC2: Encrypted %d bytes\n", byte_count);
            }
      }

      os_unlock_restore_context(scc_crypto_lock, irq_flags);

out:
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18))
                              mxc_clks_disable(SCC_CLK);
#else
                              if (scc_clk != ERR_PTR(ENOENT))
                                    clk_disable(scc_clk);
#endif

      return status;
}


Generated by  Doxygen 1.6.0   Back to index