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

scc_return_t scc_decrypt_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 
)

Decrypt a region into secure memory

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

Definition at line 1439 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_DEC_CBC, SCM_CCMD_AES_DEC_ECB, SCM_CCMD_OFFSET_SHIFT, SCM_CCMD_PART_SHIFT, and SCM_PART_NUMBER.

Referenced by do_scc_decrypt_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();

    /*Enabling SCC clock.*/
#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_DEC_CBC;
            break;
      case SCC_CYPHER_MODE_ECB:
            scm_command |= SCM_CCMD_AES_DEC_ECB;
            break;
      default:
            status = SCC_RET_FAIL;
            break;
      }

      pr_debug("Received decrypt 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) {
            status = SCC_RET_FAIL;  /* reset expectations */
            SCC_WRITE_REGISTER(SCM_C_BLACK_ST_REG, (uint32_t) black_data);

            /* 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 decryption */
            crypto_status = scc_do_crypto(byte_count, scm_command);

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

      os_unlock_restore_context(scc_crypto_lock, irq_flags);
out:
    /*Disabling the Clock when the driver is not in use.*/
#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