X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=arch%2Farm%2Fmach-imx%2Fcmd_dek.c;h=b65bf874b83788ebac9b11535e893fb2dfece6d8;hb=6cc04547cb3bbd3a3d78947f200acbae19e3c67f;hp=5f21d2b1c50967368cb0bcf47a2b293805886e0e;hpb=09140113108541b95d340f3c7b6ee597d31ccc73;p=platform%2Fkernel%2Fu-boot.git diff --git a/arch/arm/mach-imx/cmd_dek.c b/arch/arm/mach-imx/cmd_dek.c index 5f21d2b..b65bf87 100644 --- a/arch/arm/mach-imx/cmd_dek.c +++ b/arch/arm/mach-imx/cmd_dek.c @@ -7,12 +7,20 @@ #include #include +#include #include +#include #include #include #include #include #include +#include +#ifdef CONFIG_IMX_SECO_DEK_ENCAP +#include +#include +#endif +#include /** * blob_dek() - Encapsulate the DEK as a blob using CAM's Key @@ -22,16 +30,20 @@ * * Returns zero on success,and negative on error. */ -static int blob_encap_dek(const u8 *src, u8 *dst, u32 len) +#ifdef CONFIG_IMX_CAAM_DEK_ENCAP +static int blob_encap_dek(u32 src_addr, u32 dst_addr, u32 len) { - int ret = 0; - u32 jr_size = 4; + u8 *src_ptr, *dst_ptr; + + src_ptr = map_sysmem(src_addr, len / 8); + dst_ptr = map_sysmem(dst_addr, BLOB_SIZE(len / 8)); + + hab_caam_clock_enable(1); - u32 out_jr_size = sec_in32(CONFIG_SYS_FSL_JR0_ADDR + 0x102c); - if (out_jr_size != jr_size) { - hab_caam_clock_enable(1); + u32 out_jr_size = sec_in32(CFG_SYS_FSL_JR0_ADDR + + FSL_CAAM_ORSR_JRa_OFFSET); + if (out_jr_size != FSL_CAAM_MAX_JR_SIZE) sec_init(); - } if (!((len == 128) | (len == 192) | (len == 256))) { debug("Invalid DEK size. Valid sizes are 128, 192 and 256b\n"); @@ -39,10 +51,237 @@ static int blob_encap_dek(const u8 *src, u8 *dst, u32 len) } len /= 8; - ret = blob_dek(src, dst, len); + return blob_dek(src_ptr, dst_ptr, len); +} +#endif /* CONFIG_IMX_CAAM_DEK_ENCAP */ + +#ifdef CONFIG_IMX_OPTEE_DEK_ENCAP + +#define PTA_DEK_BLOB_PTA_UUID {0xef477737, 0x0db1, 0x4a9d, \ + {0x84, 0x37, 0xf2, 0xf5, 0x35, 0xc0, 0xbd, 0x92} } + +#define OPTEE_BLOB_HDR_SIZE 8 + +static int blob_encap_dek(u32 src_addr, u32 dst_addr, u32 len) +{ + struct udevice *dev = NULL; + struct tee_shm *shm_input, *shm_output; + struct tee_open_session_arg arg = {0}; + struct tee_invoke_arg arg_func = {0}; + const struct tee_optee_ta_uuid uuid = PTA_DEK_BLOB_PTA_UUID; + struct tee_param param[4] = {0}; + int ret; + + /* Get tee device */ + dev = tee_find_device(NULL, NULL, NULL, NULL); + if (!dev) { + printf("Cannot get OP-TEE device\n"); + return -1; + } + + /* Set TA UUID */ + tee_optee_ta_uuid_to_octets(arg.uuid, &uuid); + + /* Open TA session */ + ret = tee_open_session(dev, &arg, 0, NULL); + if (ret < 0) { + printf("Cannot open session with PTA Blob 0x%X\n", ret); + return -1; + } + + /* Allocate shared input and output buffers for TA */ + ret = tee_shm_register(dev, (void *)(ulong)src_addr, len / 8, 0x0, &shm_input); + if (ret < 0) { + printf("Cannot register input shared memory 0x%X\n", ret); + goto error; + } + + ret = tee_shm_register(dev, (void *)(ulong)dst_addr, + BLOB_SIZE(len / 8) + OPTEE_BLOB_HDR_SIZE, + 0x0, &shm_output); + if (ret < 0) { + printf("Cannot register output shared memory 0x%X\n", ret); + goto error; + } + + param[0].u.memref.shm = shm_input; + param[0].u.memref.size = shm_input->size; + param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT; + param[1].u.memref.shm = shm_output; + param[1].u.memref.size = shm_output->size; + param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT; + param[2].attr = TEE_PARAM_ATTR_TYPE_NONE; + param[3].attr = TEE_PARAM_ATTR_TYPE_NONE; + + arg_func.func = 0; + arg_func.session = arg.session; + + /* Generate DEK blob */ + arg_func.session = arg.session; + ret = tee_invoke_func(dev, &arg_func, 4, param); + if (ret < 0) + printf("Cannot generate Blob with PTA DEK Blob 0x%X\n", ret); + +error: + /* Free shared memory */ + tee_shm_free(shm_input); + tee_shm_free(shm_output); + + /* Close session */ + ret = tee_close_session(dev, arg.session); + if (ret < 0) + printf("Cannot close session with PTA DEK Blob 0x%X\n", ret); + + return ret; +} +#endif /* CONFIG_IMX_OPTEE_DEK_ENCAP */ +#ifdef CONFIG_IMX_SECO_DEK_ENCAP + +#define DEK_BLOB_KEY_ID 0x0 + +#define AHAB_PRIVATE_KEY 0x81 +#define AHAB_VERSION 0x00 +#define AHAB_MODE_CBC 0x67 +#define AHAB_ALG_AES 0x55 +#define AHAB_128_AES_KEY 0x10 +#define AHAB_192_AES_KEY 0x18 +#define AHAB_256_AES_KEY 0x20 +#define AHAB_FLAG_KEK 0x80 +#define AHAB_DEK_BLOB 0x01 + +#define DEK_BLOB_HDR_SIZE 8 +#define SECO_PT 2U + +static int blob_encap_dek(u32 src_addr, u32 dst_addr, u32 len) +{ + sc_err_t err; + sc_rm_mr_t mr_input, mr_output; + struct generate_key_blob_hdr hdr; + u8 in_size, out_size; + u8 *src_ptr, *dst_ptr; + int ret = 0; + int i; + + /* Set sizes */ + in_size = sizeof(struct generate_key_blob_hdr) + len / 8; + out_size = BLOB_SIZE(len / 8) + DEK_BLOB_HDR_SIZE; + + /* Get src and dst virtual addresses */ + src_ptr = map_sysmem(src_addr, in_size); + dst_ptr = map_sysmem(dst_addr, out_size); + + /* Check addr input */ + if (!(src_ptr && dst_ptr)) { + debug("src_addr or dst_addr invalid\n"); + return -1; + } + + /* Build key header */ + hdr.version = AHAB_VERSION; + hdr.length_lsb = sizeof(struct generate_key_blob_hdr) + len / 8; + hdr.length_msb = 0x00; + hdr.tag = AHAB_PRIVATE_KEY; + hdr.flags = AHAB_DEK_BLOB; + hdr.algorithm = AHAB_ALG_AES; + hdr.mode = AHAB_MODE_CBC; + + switch (len) { + case 128: + hdr.size = AHAB_128_AES_KEY; + break; + case 192: + hdr.size = AHAB_192_AES_KEY; + break; + case 256: + hdr.size = AHAB_256_AES_KEY; + break; + default: + /* Not supported */ + debug("Invalid DEK size. Valid sizes are 128, 192 and 256b\n"); + return -1; + } + + /* Build input message */ + memmove((void *)(src_ptr + sizeof(struct generate_key_blob_hdr)), + (void *)src_ptr, len / 8); + memcpy((void *)src_ptr, (void *)&hdr, + sizeof(struct generate_key_blob_hdr)); + + /* Flush the cache before triggering the CAAM DMA */ + flush_dcache_range(src_addr, src_addr + in_size); + + /* Find input memory region */ + err = sc_rm_find_memreg((-1), &mr_input, src_addr & ~(CONFIG_SYS_CACHELINE_SIZE - 1), + ALIGN(src_addr + in_size, CONFIG_SYS_CACHELINE_SIZE)); + if (err) { + printf("Error: find memory region 0x%X\n", src_addr); + return -ENOMEM; + } + + /* Find output memory region */ + err = sc_rm_find_memreg((-1), &mr_output, dst_addr & ~(CONFIG_SYS_CACHELINE_SIZE - 1), + ALIGN(dst_addr + out_size, CONFIG_SYS_CACHELINE_SIZE)); + if (err) { + printf("Error: find memory region 0x%X\n", dst_addr); + return -ENOMEM; + } + + /* Set memory region permissions for SECO */ + err = sc_rm_set_memreg_permissions(-1, mr_input, SECO_PT, + SC_RM_PERM_FULL); + if (err) { + printf("Set permission failed for input memory region\n"); + ret = -EPERM; + goto error; + } + + err = sc_rm_set_memreg_permissions(-1, mr_output, SECO_PT, + SC_RM_PERM_FULL); + if (err) { + printf("Set permission failed for output memory region\n"); + ret = -EPERM; + goto error; + } + + /* Flush output data before SECO operation */ + flush_dcache_range((ulong)dst_ptr, (ulong)(dst_ptr + + roundup(out_size, ARCH_DMA_MINALIGN))); + + /* Generate DEK blob */ + err = sc_seco_gen_key_blob((-1), 0x0, src_addr, dst_addr, out_size); + if (err) { + ret = -EPERM; + goto error; + } + + /* Invalidate output buffer */ + invalidate_dcache_range((ulong)dst_ptr, (ulong)(dst_ptr + + roundup(out_size, ARCH_DMA_MINALIGN))); + + printf("DEK Blob\n"); + for (i = 0; i < DEK_BLOB_HDR_SIZE + BLOB_SIZE(len / 8); i++) + printf("%02X", dst_ptr[i]); + printf("\n"); + +error: + /* Remove memory region permission to SECO */ + err = sc_rm_set_memreg_permissions(-1, mr_input, SECO_PT, + SC_RM_PERM_NONE); + if (err) { + printf("Error: remove permission failed for input\n"); + ret = -EPERM; + } + + err = sc_rm_set_memreg_permissions(-1, mr_output, SECO_PT, + SC_RM_PERM_NONE); + if (err) { + printf("Error: remove permission failed for output\n"); + ret = -EPERM; + } return ret; } +#endif /* CONFIG_IMX_SECO_DEK_ENCAP */ /** * do_dek_blob() - Handle the "dek_blob" command-line command @@ -58,22 +297,15 @@ static int do_dek_blob(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { uint32_t src_addr, dst_addr, len; - uint8_t *src_ptr, *dst_ptr; - int ret = 0; if (argc != 4) return CMD_RET_USAGE; - src_addr = simple_strtoul(argv[1], NULL, 16); - dst_addr = simple_strtoul(argv[2], NULL, 16); - len = simple_strtoul(argv[3], NULL, 10); - - src_ptr = map_sysmem(src_addr, len/8); - dst_ptr = map_sysmem(dst_addr, BLOB_SIZE(len/8)); + src_addr = hextoul(argv[1], NULL); + dst_addr = hextoul(argv[2], NULL); + len = dectoul(argv[3], NULL); - ret = blob_encap_dek(src_ptr, dst_ptr, len); - - return ret; + return blob_encap_dek(src_addr, dst_addr, len); } /***************************************************/