| // SPDX-License-Identifier: GPL-2.0+ |
| /* |
| * Copyright 2016 Freescale Semiconductor, Inc. |
| * Copyright 2017 NXP |
| * |
| * These commands enable the use of the CAAM MPPubK-generation and MPSign |
| * functions in supported i.MX devices. |
| */ |
| |
| #include <asm/byteorder.h> |
| #include <asm/arch/clock.h> |
| #include <linux/compiler.h> |
| #include <command.h> |
| #include <common.h> |
| #include <environment.h> |
| #include <fsl_sec.h> |
| #include <mapmem.h> |
| #include <memalign.h> |
| |
| DECLARE_GLOBAL_DATA_PTR; |
| |
| /** |
| * do_mfgprot() - Handle the "mfgprot" command-line command |
| * @cmdtp: Command data struct pointer |
| * @flag: Command flag |
| * @argc: Command-line argument count |
| * @argv: Array of command-line arguments |
| * |
| * Returns zero on success, CMD_RET_USAGE in case of misuse and negative |
| * on error. |
| */ |
| static int do_mfgprot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) |
| { |
| u8 *m_ptr, *dgst_ptr, *c_ptr, *d_ptr, *dst_ptr; |
| char *pubk, *sign, *sel; |
| int m_size, i, ret; |
| u32 m_addr; |
| |
| pubk = "pubk"; |
| sign = "sign"; |
| sel = argv[1]; |
| |
| /* Enable HAB clock */ |
| hab_caam_clock_enable(1); |
| |
| u32 out_jr_size = sec_in32(CONFIG_SYS_FSL_JR0_ADDR + |
| FSL_CAAM_ORSR_JRa_OFFSET); |
| |
| if (out_jr_size != FSL_CAAM_MAX_JR_SIZE) |
| sec_init(); |
| |
| if (strcmp(sel, pubk) == 0) { |
| dst_ptr = malloc_cache_aligned(FSL_CAAM_MP_PUBK_BYTES); |
| if (!dst_ptr) |
| return -ENOMEM; |
| |
| ret = gen_mppubk(dst_ptr); |
| if (ret) { |
| free(dst_ptr); |
| return ret; |
| } |
| |
| /* Output results */ |
| puts("Public key:\n"); |
| for (i = 0; i < FSL_CAAM_MP_PUBK_BYTES; i++) |
| printf("%02X", (dst_ptr)[i]); |
| puts("\n"); |
| free(dst_ptr); |
| |
| } else if (strcmp(sel, sign) == 0) { |
| if (argc != 4) |
| return CMD_RET_USAGE; |
| |
| m_addr = hextoul(argv[2], NULL); |
| m_size = dectoul(argv[3], NULL); |
| m_ptr = map_physmem(m_addr, m_size, MAP_NOCACHE); |
| if (!m_ptr) |
| return -ENOMEM; |
| |
| dgst_ptr = malloc_cache_aligned(FSL_CAAM_MP_MES_DGST_BYTES); |
| if (!dgst_ptr) { |
| ret = -ENOMEM; |
| goto free_m; |
| } |
| |
| c_ptr = malloc_cache_aligned(FSL_CAAM_MP_PRVK_BYTES); |
| if (!c_ptr) { |
| ret = -ENOMEM; |
| goto free_dgst; |
| } |
| |
| d_ptr = malloc_cache_aligned(FSL_CAAM_MP_PRVK_BYTES); |
| if (!d_ptr) { |
| ret = -ENOMEM; |
| goto free_c; |
| } |
| |
| ret = sign_mppubk(m_ptr, m_size, dgst_ptr, c_ptr, d_ptr); |
| if (ret) |
| goto free_d; |
| |
| /* Output results */ |
| puts("Message: "); |
| for (i = 0; i < m_size; i++) |
| printf("%02X ", (m_ptr)[i]); |
| puts("\n"); |
| |
| puts("Message Representative Digest(SHA-256):\n"); |
| for (i = 0; i < FSL_CAAM_MP_MES_DGST_BYTES; i++) |
| printf("%02X", (dgst_ptr)[i]); |
| puts("\n"); |
| |
| puts("Signature:\n"); |
| puts("C:\n"); |
| for (i = 0; i < FSL_CAAM_MP_PRVK_BYTES; i++) |
| printf("%02X", (c_ptr)[i]); |
| puts("\n"); |
| |
| puts("d:\n"); |
| for (i = 0; i < FSL_CAAM_MP_PRVK_BYTES; i++) |
| printf("%02X", (d_ptr)[i]); |
| puts("\n"); |
| free_d: |
| free(d_ptr); |
| free_c: |
| free(c_ptr); |
| free_dgst: |
| free(dgst_ptr); |
| free_m: |
| unmap_sysmem(m_ptr); |
| |
| } else { |
| return CMD_RET_USAGE; |
| } |
| return ret; |
| } |
| |
| /***************************************************/ |
| static char mfgprot_help_text[] = |
| "Usage:\n" |
| "Print the public key for Manufacturing Protection\n" |
| "\tmfgprot pubk\n" |
| "Generates a Manufacturing Protection signature\n" |
| "\tmfgprot sign <data_addr> <size>"; |
| |
| U_BOOT_CMD( |
| mfgprot, 4, 1, do_mfgprot, |
| "Manufacturing Protection\n", |
| mfgprot_help_text |
| ); |