uboot/drivers/crypto/fsl/jobdesc.c
<<
>>
Prefs
   1/*
   2 * SEC Descriptor Construction Library
   3 * Basic job descriptor construction
   4 *
   5 * Copyright 2014 Freescale Semiconductor, Inc.
   6 *
   7 * SPDX-License-Identifier:     GPL-2.0+
   8 *
   9 */
  10
  11#include <common.h>
  12#include <fsl_sec.h>
  13#include "desc_constr.h"
  14#include "jobdesc.h"
  15#include "rsa_caam.h"
  16
  17#if defined(CONFIG_MX6) || defined(CONFIG_MX7)
  18/*!
  19 * Secure memory run command
  20 *
  21 * @param   sec_mem_cmd  Secure memory command register
  22 * @return  cmd_status  Secure memory command status register
  23 */
  24uint32_t secmem_set_cmd(uint32_t sec_mem_cmd)
  25{
  26        uint32_t temp_reg;
  27
  28        ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
  29        uint32_t sm_vid = SM_VERSION(sec_in32(&sec->smvid));
  30        uint32_t jr_id = 0;
  31
  32        sec_out32(CAAM_SMCJR(sm_vid, jr_id), sec_mem_cmd);
  33
  34        do {
  35                temp_reg = sec_in32(CAAM_SMCSJR(sm_vid, jr_id));
  36        } while (temp_reg & CMD_COMPLETE);
  37
  38        return temp_reg;
  39}
  40
  41/*!
  42 * CAAM page allocation:
  43 * Allocates a partition from secure memory, with the id
  44 * equal to partion_num. This will de-allocate the page
  45 * if it is already allocated. The partition will have
  46 * full access permissions. The permissions are set before,
  47 * running a job descriptor. A memory page of secure RAM
  48 * is allocated for the partition.
  49 *
  50 * @param   page  Number of the page to allocate.
  51 * @param   partition  Number of the partition to allocate.
  52 * @return  0 on success, ERROR_IN_PAGE_ALLOC otherwise
  53 */
  54int caam_page_alloc(uint8_t page_num, uint8_t partition_num)
  55{
  56        uint32_t temp_reg;
  57
  58        ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
  59        uint32_t sm_vid = SM_VERSION(sec_in32(&sec->smvid));
  60        uint32_t jr_id = 0;
  61
  62        /*
  63         * De-Allocate partition_num if already allocated to ARM core
  64         */
  65        if (sec_in32(CAAM_SMPO_0) & PARTITION_OWNER(partition_num)) {
  66                temp_reg = secmem_set_cmd(PARTITION(partition_num) |
  67                                                CMD_PART_DEALLOC);
  68                if (temp_reg & SMCSJR_AERR) {
  69                        printf("Error: De-allocation status 0x%X\n", temp_reg);
  70                        return ERROR_IN_PAGE_ALLOC;
  71                }
  72        }
  73
  74        /* set the access rights to allow full access */
  75        sec_out32(CAAM_SMAG1JR(sm_vid, jr_id, partition_num), 0xF);
  76        sec_out32(CAAM_SMAG2JR(sm_vid, jr_id, partition_num), 0xF);
  77        sec_out32(CAAM_SMAPJR(sm_vid, jr_id, partition_num), 0xFF);
  78
  79        /* Now need to allocate partition_num of secure RAM. */
  80        /* De-Allocate page_num by starting with a page inquiry command */
  81        temp_reg = secmem_set_cmd(PAGE(page_num) | CMD_INQUIRY);
  82
  83        /* if the page is owned, de-allocate it */
  84        if ((temp_reg & SMCSJR_PO) == PAGE_OWNED) {
  85                temp_reg = secmem_set_cmd(PAGE(page_num) | CMD_PAGE_DEALLOC);
  86                if (temp_reg & SMCSJR_AERR) {
  87                        printf("Error: Allocation status 0x%X\n", temp_reg);
  88                        return ERROR_IN_PAGE_ALLOC;
  89                }
  90        }
  91
  92        /* Allocate page_num to partition_num */
  93        temp_reg = secmem_set_cmd(PAGE(page_num) | PARTITION(partition_num)
  94                                                | CMD_PAGE_ALLOC);
  95        if (temp_reg & SMCSJR_AERR) {
  96                printf("Error: Allocation status 0x%X\n", temp_reg);
  97                return ERROR_IN_PAGE_ALLOC;
  98        }
  99        /* page inquiry command to ensure that the page was allocated */
 100        temp_reg = secmem_set_cmd(PAGE(page_num) | CMD_INQUIRY);
 101
 102        /* if the page is not owned => problem */
 103        if ((temp_reg & SMCSJR_PO) != PAGE_OWNED) {
 104                printf("Allocation of page %d in partition %d failed 0x%X\n",
 105                       temp_reg, page_num, partition_num);
 106
 107                return ERROR_IN_PAGE_ALLOC;
 108        }
 109
 110        return 0;
 111}
 112
 113int inline_cnstr_jobdesc_blob_dek(uint32_t *desc, const uint8_t *plain_txt,
 114                                       uint8_t *dek_blob, uint32_t in_sz)
 115{
 116        ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
 117        uint32_t sm_vid = SM_VERSION(sec_in32(&sec->smvid));
 118        uint32_t jr_id = 0;
 119
 120        uint32_t ret = 0;
 121        u32 aad_w1, aad_w2;
 122        /* output blob will have 32 bytes key blob in beginning and
 123         * 16 byte HMAC identifier at end of data blob */
 124        uint32_t out_sz = in_sz + KEY_BLOB_SIZE + MAC_SIZE;
 125        /* Setting HDR for blob */
 126        uint8_t wrapped_key_hdr[8] = {HDR_TAG, 0x00, WRP_HDR_SIZE + out_sz,
 127                             HDR_PAR, HAB_MOD, HAB_ALG, in_sz, HAB_FLG};
 128
 129        /* initialize the blob array */
 130        memset(dek_blob, 0, out_sz + 8);
 131        /* Copy the header into the DEK blob buffer */
 132        memcpy(dek_blob, wrapped_key_hdr, sizeof(wrapped_key_hdr));
 133
 134        /* allocating secure memory */
 135        ret = caam_page_alloc(PAGE_1, PARTITION_1);
 136        if (ret)
 137                return ret;
 138
 139        /* Write DEK to secure memory */
 140        memcpy((uint32_t *)SEC_MEM_PAGE1, (uint32_t *)plain_txt, in_sz);
 141
 142        unsigned long start = (unsigned long)SEC_MEM_PAGE1 &
 143                                ~(ARCH_DMA_MINALIGN - 1);
 144        unsigned long end = ALIGN(start + 0x1000, ARCH_DMA_MINALIGN);
 145        flush_dcache_range(start, end);
 146
 147        /* Now configure the access rights of the partition */
 148        sec_out32(CAAM_SMAG1JR(sm_vid, jr_id, PARTITION_1), KS_G1);
 149        sec_out32(CAAM_SMAG2JR(sm_vid, jr_id, PARTITION_1), 0);
 150        sec_out32(CAAM_SMAPJR(sm_vid, jr_id, PARTITION_1), PERM);
 151
 152        /* construct aad for AES */
 153        aad_w1 = (in_sz << OP_ALG_ALGSEL_SHIFT) | KEY_AES_SRC | LD_CCM_MODE;
 154        aad_w2 = 0x0;
 155
 156        init_job_desc(desc, 0);
 157
 158        append_cmd(desc, CMD_LOAD | CLASS_2 | KEY_IMM | KEY_ENC |
 159                                (0x0c << LDST_OFFSET_SHIFT) | 0x08);
 160
 161        append_u32(desc, aad_w1);
 162
 163        append_u32(desc, aad_w2);
 164
 165        append_cmd_ptr(desc, (dma_addr_t)SEC_MEM_PAGE1, in_sz, CMD_SEQ_IN_PTR);
 166
 167        append_cmd_ptr(desc, (dma_addr_t)dek_blob + 8, out_sz, CMD_SEQ_OUT_PTR);
 168
 169        append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB |
 170                                                OP_PCLID_SECMEM);
 171
 172        return ret;
 173}
 174#endif
 175
 176void inline_cnstr_jobdesc_hash(uint32_t *desc,
 177                          const uint8_t *msg, uint32_t msgsz, uint8_t *digest,
 178                          u32 alg_type, uint32_t alg_size, int sg_tbl)
 179{
 180        /* SHA 256 , output is of length 32 words */
 181        uint32_t storelen = alg_size;
 182        u32 options;
 183        dma_addr_t dma_addr_in, dma_addr_out;
 184
 185        dma_addr_in = virt_to_phys((void *)msg);
 186        dma_addr_out = virt_to_phys((void *)digest);
 187
 188        init_job_desc(desc, 0);
 189        append_operation(desc, OP_TYPE_CLASS2_ALG |
 190                         OP_ALG_AAI_HASH | OP_ALG_AS_INITFINAL |
 191                         OP_ALG_ENCRYPT | OP_ALG_ICV_OFF | alg_type);
 192
 193        options = LDST_CLASS_2_CCB | FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST2;
 194        if (sg_tbl)
 195                options |= FIFOLDST_SGF;
 196        if (msgsz > 0xffff) {
 197                options |= FIFOLDST_EXT;
 198                append_fifo_load(desc, dma_addr_in, 0, options);
 199                append_cmd(desc, msgsz);
 200        } else {
 201                append_fifo_load(desc, dma_addr_in, msgsz, options);
 202        }
 203
 204        append_store(desc, dma_addr_out, storelen,
 205                     LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_CONTEXT);
 206}
 207
 208void inline_cnstr_jobdesc_blob_encap(uint32_t *desc, uint8_t *key_idnfr,
 209                                     uint8_t *plain_txt, uint8_t *enc_blob,
 210                                     uint32_t in_sz)
 211{
 212        dma_addr_t dma_addr_key_idnfr, dma_addr_in, dma_addr_out;
 213        uint32_t key_sz = KEY_IDNFR_SZ_BYTES;
 214        /* output blob will have 32 bytes key blob in beginning and
 215         * 16 byte HMAC identifier at end of data blob */
 216        uint32_t out_sz = in_sz + KEY_BLOB_SIZE + MAC_SIZE;
 217
 218        dma_addr_key_idnfr = virt_to_phys((void *)key_idnfr);
 219        dma_addr_in     = virt_to_phys((void *)plain_txt);
 220        dma_addr_out    = virt_to_phys((void *)enc_blob);
 221
 222        init_job_desc(desc, 0);
 223
 224        append_key(desc, dma_addr_key_idnfr, key_sz, CLASS_2);
 225
 226        append_seq_in_ptr(desc, dma_addr_in, in_sz, 0);
 227
 228        append_seq_out_ptr(desc, dma_addr_out, out_sz, 0);
 229
 230        append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB);
 231}
 232
 233void inline_cnstr_jobdesc_blob_decap(uint32_t *desc, uint8_t *key_idnfr,
 234                                     uint8_t *enc_blob, uint8_t *plain_txt,
 235                                     uint32_t out_sz)
 236{
 237        dma_addr_t dma_addr_key_idnfr, dma_addr_in, dma_addr_out;
 238        uint32_t key_sz = KEY_IDNFR_SZ_BYTES;
 239        uint32_t in_sz = out_sz + KEY_BLOB_SIZE + MAC_SIZE;
 240
 241        dma_addr_key_idnfr = virt_to_phys((void *)key_idnfr);
 242        dma_addr_in     = virt_to_phys((void *)enc_blob);
 243        dma_addr_out    = virt_to_phys((void *)plain_txt);
 244
 245        init_job_desc(desc, 0);
 246
 247        append_key(desc, dma_addr_key_idnfr, key_sz, CLASS_2);
 248
 249        append_seq_in_ptr(desc, dma_addr_in, in_sz, 0);
 250
 251        append_seq_out_ptr(desc, dma_addr_out, out_sz, 0);
 252
 253        append_operation(desc, OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB);
 254}
 255
 256/*
 257 * Descriptor to instantiate RNG State Handle 0 in normal mode and
 258 * load the JDKEK, TDKEK and TDSK registers
 259 */
 260void inline_cnstr_jobdesc_rng_instantiation(uint32_t *desc)
 261{
 262        u32 *jump_cmd;
 263
 264        init_job_desc(desc, 0);
 265
 266        /* INIT RNG in non-test mode */
 267        append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
 268                         OP_ALG_AS_INIT);
 269
 270        /* wait for done */
 271        jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1);
 272        set_jump_tgt_here(desc, jump_cmd);
 273
 274        /*
 275         * load 1 to clear written reg:
 276         * resets the done interrrupt and returns the RNG to idle.
 277         */
 278        append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
 279
 280        /* generate secure keys (non-test) */
 281        append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
 282                         OP_ALG_RNG4_SK);
 283}
 284
 285/* Change key size to bytes form bits in calling function*/
 286void inline_cnstr_jobdesc_pkha_rsaexp(uint32_t *desc,
 287                                      struct pk_in_params *pkin, uint8_t *out,
 288                                      uint32_t out_siz)
 289{
 290        dma_addr_t dma_addr_e, dma_addr_a, dma_addr_n, dma_addr_out;
 291
 292        dma_addr_e = virt_to_phys((void *)pkin->e);
 293        dma_addr_a = virt_to_phys((void *)pkin->a);
 294        dma_addr_n = virt_to_phys((void *)pkin->n);
 295        dma_addr_out = virt_to_phys((void *)out);
 296
 297        init_job_desc(desc, 0);
 298        append_key(desc, dma_addr_e, pkin->e_siz, KEY_DEST_PKHA_E | CLASS_1);
 299
 300        append_fifo_load(desc, dma_addr_a,
 301                         pkin->a_siz, LDST_CLASS_1_CCB | FIFOLD_TYPE_PK_A);
 302
 303        append_fifo_load(desc, dma_addr_n,
 304                         pkin->n_siz, LDST_CLASS_1_CCB | FIFOLD_TYPE_PK_N);
 305
 306        append_operation(desc, OP_TYPE_PK | OP_ALG_PK | OP_ALG_PKMODE_MOD_EXPO);
 307
 308        append_fifo_store(desc, dma_addr_out, out_siz,
 309                          LDST_CLASS_1_CCB | FIFOST_TYPE_PKHA_B);
 310}
 311