diff --git a/source/uboot-2021.10/arch/riscv/mach-artinchip/upg_detect.c b/source/uboot-2021.10/arch/riscv/mach-artinchip/upg_detect.c index 6acf435dc..8bbe73588 100644 --- a/source/uboot-2021.10/arch/riscv/mach-artinchip/upg_detect.c +++ b/source/uboot-2021.10/arch/riscv/mach-artinchip/upg_detect.c @@ -87,6 +87,10 @@ static int do_upgrade_detect(struct cmd_tbl *cmdtp, int flag, int argc, { int ret = 0; +#if CONFIG_ARTINCHIP_SID_BURN_SPIENC_KEY_CMD + run_command("efuse_spienc", 0); +#endif + env_set("upg_type", ""); if (check_usb_upg()) { aic_upg_flag_clear(); diff --git a/source/uboot-2021.10/board/artinchip/d211/Makefile b/source/uboot-2021.10/board/artinchip/d211/Makefile index 0b249f082..71db61432 100644 --- a/source/uboot-2021.10/board/artinchip/d211/Makefile +++ b/source/uboot-2021.10/board/artinchip/d211/Makefile @@ -3,6 +3,7 @@ obj-y += d211.o obj-y += env_location.o obj-y += efuse_cmd.o +obj-$(CONFIG_ARTINCHIP_SID_BURN_SPIENC_KEY_CMD) += efuse_burn_spienc_key_cmd.o obj-$(CONFIG_AICUPG_ARTINCHIP) += usb_device_check.o obj-$(CONFIG_UPDATE_UDISK_FATFS_ARTINCHIP) += usb_host_check.o obj-$(CONFIG_$(SPL_TPL_)ENV_IS_IN_MMC) += mmc_env.o diff --git a/source/uboot-2021.10/board/artinchip/d211/efuse_burn_spienc_key_cmd.c b/source/uboot-2021.10/board/artinchip/d211/efuse_burn_spienc_key_cmd.c new file mode 100644 index 000000000..e65848d03 --- /dev/null +++ b/source/uboot-2021.10/board/artinchip/d211/efuse_burn_spienc_key_cmd.c @@ -0,0 +1,471 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022-2025 ArtInChip Technology Co., Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "spi_aes_key.h" + +#ifndef CONFIG_SPL_BUILD + +static struct udevice *efuse_dev; +static struct udevice *get_efuse_device(void) +{ + struct udevice *dev = NULL; + int ret; + + if (efuse_dev) + return efuse_dev; + + ret = uclass_first_device_err(UCLASS_MISC, &dev); + if (ret) { + pr_err("Get UCLASS_MISC device failed.\n"); + return NULL; + } + + do { + if (device_is_compatible(dev, "artinchip,aic-sid-v1.0")) + break; + ret = uclass_next_device_err(&dev); + } while (dev); + + efuse_dev = dev; + return efuse_dev; +} + +static void hexdump(const u8 *buf, uint len) +{ + int i; + + for (i = 0; i < len; i++) { + if (i && (i % 16) == 0) + printf("\n"); + if ((i % 16) == 0) + printf("0x%08lx : ", (unsigned long)&buf[i]); + printf("%02x ", buf[i]); + } + printf("\n"); +} + +static int write_efuse(char *msg, u32 offset, const void *val, u32 size) +{ +#if CONFIG_ARTINCHIP_SID_BURN_SIMULATED + printf("eFuse %s:\n", msg); + hexdump((unsigned char *)val, size); + return size; +#else + struct udevice *dev = NULL; + int wrcnt; + + dev = get_efuse_device(); + if (!dev) { + pr_err("Failed to get efuse device.\n"); + return -1; + } + + wrcnt = misc_write(dev, offset, val, size); + if (wrcnt != size) { + pr_err("Failed to write eFuse.\n"); + return -1; + } + + return size; +#endif +} + +static int read_efuse(u32 offset, void *val, u32 size) +{ + struct udevice *dev = NULL; + int rdcnt; + + dev = get_efuse_device(); + if (!dev) { + pr_err("Failed to get efuse device.\n"); + return -1; + } + + rdcnt = misc_read(dev, offset, val, size); + if (rdcnt != size) { + pr_err("Failed to read eFuse.\n"); + return -1; + } + + return size; +} + +static int burn_brom_spienc_bit(void) +{ + u32 offset = 0xFFFF, val; + int ret; + + offset = 0x38; + val = 0; + val |= (1 << 16); // Secure boot bit for brom + val |= (1 << 19); // SPIENC boot bit for brom + + ret = write_efuse("brom enable spienc secure bit", offset, (const void *)&val, 4); + if (ret <= 0) { + printf("Write BROM SPIENC bit error\n"); + return -1; + } + + return 0; +} + +static int check_brom_spienc_bit(void) +{ + u32 offset = 0xFFFF, val, mskval = 0; + int ret; + + offset = 0x38; + mskval = 0; + mskval |= (1 << 16); // Secure boot bit for brom + mskval |= (1 << 19); // SPIENC boot bit for brom + + ret = read_efuse(offset, (void *)&val, 4); + if (ret <= 0) { + printf("Read secure bit efuse error.\n"); + return -1; + } + + if ((val & mskval) == mskval) { + printf("BROM SPIENC is ENABLED\n"); + } else { + printf("BROM SPIENC is NOT enabled\n"); + } + + return 0; +} + +static int burn_jtag_lock_bit(void) +{ + u32 offset = 0xFFFF, val; + int ret; + + offset = 0x38; + val = 0; + val |= (1 << 0); // JTAG LOCK + + ret = write_efuse("jtag lock bit", offset, (const void *)&val, 4); + if (ret <= 0) { + printf("Write JTAG LOCK bit error\n"); + return -1; + } + + return 0; +} + +static int check_jtag_lock_bit(void) +{ + u32 offset = 0xFFFF, val, mskval = 0; + int ret; + + offset = 0x38; + mskval = 0; + mskval |= (1 << 0); // JTAG LOCK + + ret = read_efuse(offset, (void *)&val, 4); + if (ret <= 0) { + printf("Read secure bit efuse error.\n"); + return -1; + } + + if ((val & mskval) == mskval) { + printf("JTAG LOCK is ENABLED\n"); + } else { + printf("JTAG LOCK is NOT enabled\n"); + } + + return 0; +} + +static int burn_spienc_key(void) +{ + u32 offset = 0xFFFF; + int ret; + + offset = 0xA0; + + ret = write_efuse("spi_aes.key", offset, (const void *)spi_aes_key, spi_aes_key_len); + if (ret <= 0) { + printf("Write SPI ENC AES key error.\n"); + return -1; + } + + return 0; +} + +static int check_spienc_key(void) +{ + u32 offset = 0xFFFF; + u8 data[256]; + int ret; + + offset = 0xA0; + + ret = read_efuse(offset, (void *)data, 16); + if (ret <= 0) { + printf("Read efuse error.\n"); + return -1; + } + + printf("SPI ENC KEY:\n"); + hexdump(data, 16); + + return 0; +} + +static int burn_spienc_nonce(void) +{ + u32 offset; + int ret; + + offset = 0xB0; + ret = write_efuse("spi_nonce.key", offset, (const void *)spi_nonce_key, + spi_nonce_key_len); + if (ret <= 0) { + printf("Write SPI ENC NONCE key error.\n"); + return -1; + } + + return 0; +} + +static int check_spienc_nonce(void) +{ + u32 offset; + u8 data[256]; + int ret; + + offset = 0xB0; + ret = read_efuse(offset, (void *)data, 8); + if (ret <= 0) { + printf("Read efuse error.\n"); + return -1; + } + + printf("SPI ENC NONCE:\n"); + hexdump(data, 8); + + return 0; +} + +static int burn_spienc_rotpk(void) +{ + u32 offset = 0xFFFF; + int ret; + + offset = 0x40; + ret = write_efuse("rotpk.bin", offset, (const void *)rotpk_bin, + rotpk_bin_len); + if (ret <= 0) { + printf("Write SPI ENC ROTPK error.\n"); + return -1; + } + + return 0; +} + +static int check_spienc_rotpk(void) +{ + u32 offset = 0xFFFF; + u8 data[256]; + int ret; + + offset = 0x40; + ret = read_efuse(offset, (void *)data, 16); + if (ret <= 0) { + printf("Read efuse error.\n"); + return -1; + } + + printf("ROTPK:\n"); + hexdump(data, 16); + + return 0; +} + +static int burn_spienc_key_read_write_disable_bits(void) +{ + u32 offset, val; + int ret; + + // SPIENC KEY and NONCE + offset = 0x4; + val = 0; + val = 0x00003F00; // SPIENC Key and Nonce Read disable + ret = write_efuse("spienc key/nonce r dis", offset, (const void *)&val, + 4); + if (ret <= 0) { + printf("Write r/w disable bit efuse error.\n"); + return -1; + } + + // ROTPK + offset = 0x8; + val = 0; + val = 0x000F0000; // ROTPK Write disable + ret = write_efuse("rotpk w dis", offset, (const void *)&val, 4); + if (ret <= 0) { + printf("Write r/w disable bit efuse error.\n"); + return -1; + } + // SPIENC KEY and NONCE + offset = 0xC; + val = 0; + val = 0x00003F00; // SPIENC Key Write disable + ret = write_efuse("spienc key/nonce w dis", offset, (const void *)&val, + 4); + if (ret <= 0) { + printf("Write r/w disable bit efuse error.\n"); + return -1; + } + + return 0; +} + +static int check_spienc_key_read_write_disable_bits(void) +{ + u32 offset, val, mskval; + int ret; + + offset = 0x4; + mskval = 0x00003F00; + ret = read_efuse(offset, (void *)&val, 4); + if (ret <= 0) { + printf("Read read disable bit efuse error.\n"); + return -1; + } + + if ((val & mskval) == mskval) + printf("SPI ENC Key is read DISABLED\n"); + else + printf("SPI ENC Key is NOT read disabled\n"); + + offset = 0x8; + mskval = 0x000F0000; + ret = read_efuse(offset, (void *)&val, 4); + if (ret <= 0) { + printf("Read write disable bit efuse error.\n"); + return -1; + } + + if ((val & mskval) == mskval) + printf("SPI ENC ROTPK is write DISABLED\n"); + else + printf("SPI ENC ROTPK is NOT write disabled\n"); + + offset = 0xC; + mskval = 0x00003F00; + ret = read_efuse(offset, (void *)&val, 4); + if (ret <= 0) { + printf("Read write disable bit efuse error.\n"); + return -1; + } + + if ((val & mskval) == mskval) + printf("SPI ENC Key is write DISABLED\n"); + else + printf("SPI ENC Key is NOT write disabled\n"); + + return 0; +} + +int cmd_efuse_do_spienc(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + int ret; + + ret = burn_brom_spienc_bit(); + if (ret) { + printf("Error\n"); + return -1; + } + + ret = burn_spienc_key(); + if (ret) { + printf("Error\n"); + return -1; + } + + ret = burn_spienc_nonce(); + if (ret) { + printf("Error\n"); + return -1; + } + + ret = burn_spienc_rotpk(); + if (ret) { + printf("Error\n"); + return -1; + } + + ret = burn_spienc_key_read_write_disable_bits(); + if (ret) { + printf("Error\n"); + return -1; + } + + ret = burn_jtag_lock_bit(); + if (ret) { + printf("Error\n"); + return -1; + } + + ret = check_brom_spienc_bit(); + if (ret) { + printf("Error\n"); + return -1; + } + + ret = check_jtag_lock_bit(); + if (ret) { + printf("Error\n"); + return -1; + } + ret = check_spienc_key(); + if (ret) { + printf("Error\n"); + return -1; + } + + ret = check_spienc_nonce(); + if (ret) { + printf("Error\n"); + return -1; + } + + ret = check_spienc_rotpk(); + if (ret) { + printf("Error\n"); + return -1; + } + + ret = check_spienc_key_read_write_disable_bits(); + if (ret) { + printf("Error\n"); + return -1; + } + + printf("\n"); + printf("Write SPI ENC eFuse done.\n"); +#if CONFIG_ARTINCHIP_SID_BURN_SIMULATED + printf("WARNING: This is a dry run to check the eFuse content, key is not burn to eFuse yet.\n"); +#endif +#if !CONFIG_ARTINCHIP_SID_CONTINUE_BOOT_BURN_AFTER + while (1) + continue; +#endif + return 0; +} + +U_BOOT_CMD(efuse_spienc, 1, 1, cmd_efuse_do_spienc, + "ArtInChip eFuse burn spienc command", ""); + +#endif diff --git a/source/uboot-2021.10/cmd/mtd.c b/source/uboot-2021.10/cmd/mtd.c index 8e99c4f02..691b02b18 100644 --- a/source/uboot-2021.10/cmd/mtd.c +++ b/source/uboot-2021.10/cmd/mtd.c @@ -227,6 +227,37 @@ static int do_mtd_list(struct cmd_tbl *cmdtp, int flag, int argc, return CMD_RET_SUCCESS; } +#ifdef CONFIG_ARTINCHIP_SPIENC +#include +#include +static int do_mtd_bypass(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct udevice *dev = NULL; + unsigned long status; + + if (argc < 2) + return CMD_RET_USAGE; + + status = hextoul(argv[1], NULL); + + uclass_first_device_err(UCLASS_MISC, &dev); + do { + if (device_is_compatible(dev, "artinchip,aic-spienc-v1.0")) + break; + else + dev = NULL; + uclass_next_device_err(&dev); + } while (dev); + + if (dev) { + return misc_ioctl(dev, AIC_SPIENC_IOCTL_BYPASS, (void *)status); + } else { + return CMD_RET_FAILURE; + } +} +#endif + static int mtd_special_write_oob(struct mtd_info *mtd, u64 off, struct mtd_oob_ops *io_op, bool write_empty_pages, bool woob) @@ -586,6 +617,9 @@ static int mtd_name_complete(int argc, char *const argv[], char last_char, static char mtd_help_text[] = "- generic operations on memory technology devices\n\n" "mtd list\n" +#ifdef CONFIG_ARTINCHIP_SPIENC + "mtd bypass \n" +#endif "mtd read[.raw][.oob] [ []]\n" "mtd dump[.raw][.oob] [ []]\n" "mtd write[.raw][.oob][.dontskipff] [ []]\n" @@ -596,6 +630,9 @@ static char mtd_help_text[] = "mtd mark [\n" "\n" "With:\n" +#ifdef CONFIG_ARTINCHIP_SPIENC + "\t: 1;bypass spienc, 0;enable spienc\n" +#endif "\t: NAND partition/chip name (or corresponding DM device name or OF path)\n" "\t: user address from/to which data will be retrieved/stored\n" "\t: offset in in bytes (default: start of the part)\n" @@ -610,6 +647,10 @@ static char mtd_help_text[] = U_BOOT_CMD_WITH_SUBCMDS(mtd, "MTD utils", mtd_help_text, U_BOOT_SUBCMD_MKENT(list, 1, 1, do_mtd_list), +#ifdef CONFIG_ARTINCHIP_SPIENC + U_BOOT_SUBCMD_MKENT_COMPLETE(bypass, 2, 0, do_mtd_bypass, + mtd_name_complete), +#endif U_BOOT_SUBCMD_MKENT_COMPLETE(read, 5, 0, do_mtd_io, mtd_name_complete), U_BOOT_SUBCMD_MKENT_COMPLETE(write, 5, 0, do_mtd_io, diff --git a/source/uboot-2021.10/drivers/aicupg/Kconfig b/source/uboot-2021.10/drivers/aicupg/Kconfig index 474aabcb4..bbd3ab907 100644 --- a/source/uboot-2021.10/drivers/aicupg/Kconfig +++ b/source/uboot-2021.10/drivers/aicupg/Kconfig @@ -27,10 +27,16 @@ config AICUPG_FORCE_USBUPG_SUPPORT bool "Force USB upgrading check during boot" default n +config AICUPG_FIRMWARE_SECURITY + bool "Secure transfer firmware and burn" + default n + depends on ARTINCHIP_SPIENC + config AICUPG_LOG_BUFFER_SUPPORT bool "Support to get log buffer from device" default y endif + if AICUPG_LOG_BUFFER_SUPPORT config AICUPG_LOG_BUFFER_ADDR hex "Log buffer start address" diff --git a/source/uboot-2021.10/drivers/aicupg/Makefile b/source/uboot-2021.10/drivers/aicupg/Makefile index d3c996ff1..71f6961aa 100644 --- a/source/uboot-2021.10/drivers/aicupg/Makefile +++ b/source/uboot-2021.10/drivers/aicupg/Makefile @@ -10,7 +10,19 @@ obj-$(CONFIG_AICUPG_NAND_ARTINCHIP) += nand_fwc.o obj-$(CONFIG_AICUPG_NOR_ARTINCHIP) += nor_fwc.o obj-$(CONFIG_AICUPG_MMC_ARTINCHIP) += mmc_fwc.o +ifneq ($(wildcard $(srctree)/drivers/aicupg/libfirmware_security.a),) +$(shell cp $(srctree)/drivers/aicupg/libfirmware_security.a $(obj)/libfirmware_security.a) +obj-$(CONFIG_AICUPG_FIRMWARE_SECURITY) += libfirmware_security.a +else +quiet_cmd_ar = AR $@ + cmd_ar = $(AR) crs $@ $^ + +$(obj)/libfirmware_security.a: $(obj)/firmware_security.o + $(Q)$(AR) crs $@ $^ + +obj-$(CONFIG_AICUPG_FIRMWARE_SECURITY) += libfirmware_security.a +endif + ifdef CONFIG_TARGET_D211 obj-$(CONFIG_AICUPG_NAND_ARTINCHIP) += nand_fwc_spl.o endif - diff --git a/source/uboot-2021.10/drivers/aicupg/nand_fwc.c b/source/uboot-2021.10/drivers/aicupg/nand_fwc.c index 75708fa75..826eb6e95 100644 --- a/source/uboot-2021.10/drivers/aicupg/nand_fwc.c +++ b/source/uboot-2021.10/drivers/aicupg/nand_fwc.c @@ -15,6 +15,7 @@ #include "nand_fwc_priv.h" #include "upg_internal.h" #include "nand_fwc_spl.h" +#include #ifdef CONFIG_NAND_BBT_MANAGE #include @@ -938,6 +939,10 @@ void nand_fwc_start(struct fwc_info *fwc) memset(priv, 0, sizeof(struct aicupg_nand_priv)); fwc->priv = priv; +#ifdef CONFIG_AICUPG_FIRMWARE_SECURITY + firmware_security_init(); +#endif + /* * If the meta.name contains the "image" string, the program is going to * write data to the partition, otherwise the the program is going to read @@ -961,6 +966,7 @@ void nand_fwc_start(struct fwc_info *fwc) goto err; } fwc->block_size = mtd->writesize; + if (strstr(fwc->meta.name, "target.spl")) { ret = nand_fwc_spl_prepare(fwc); if (ret) { @@ -1059,11 +1065,25 @@ static s32 nand_fwc_mtd_writer(struct fwc_info *fwc, u8 *buf, s32 len) if (!priv) return 0; + if ((fwc->meta.size - fwc->trans_size) < len) + calc_len = fwc->meta.size - fwc->trans_size; + else + calc_len = len; + + fwc->calc_partition_crc = crc32(fwc->calc_partition_crc, buf, calc_len); + +#ifdef CONFIG_AICUPG_FIRMWARE_SECURITY + firmware_security_decrypt(buf, len); +#endif + +#ifdef CONFIG_AICUPG_SINGLE_TRANS_BURN_CRC32_VERIFY rdbuf = malloc(len); if (!rdbuf) { pr_err("Error: malloc buffer failed.\n"); return 0; } +#endif + for (i = 0; i < MAX_DUPLICATED_PART; i++) { mtd = priv->mtds[i]; if (!mtd) @@ -1088,41 +1108,35 @@ static s32 nand_fwc_mtd_writer(struct fwc_info *fwc, u8 *buf, s32 len) pr_err("Write mtd %s error.\n", mtd->name); return 0; } +#ifdef CONFIG_AICUPG_SINGLE_TRANS_BURN_CRC32_VERIFY // Read data to calc crc ret = mtd_read(mtd, offs, mtd->writesize, &retlen, buf_to_read); if (ret) { - pr_err("Write mtd %s error.\n", mtd->name); + pr_err("Read mtd %s error.\n", mtd->name); return 0; } + buf_to_read += retlen; +#endif /* Update for next write */ buf_to_write += retlen; - buf_to_read += retlen; priv->offs[i] = offs + retlen; offs = priv->offs[i]; } } - if ((fwc->meta.size - fwc->trans_size) < len) - calc_len = fwc->meta.size - fwc->trans_size; - else - calc_len = len; - - fwc->calc_partition_crc = crc32(fwc->calc_partition_crc, - rdbuf, calc_len); #ifdef CONFIG_AICUPG_SINGLE_TRANS_BURN_CRC32_VERIFY fwc->calc_trans_crc = crc32(fwc->calc_trans_crc, buf, calc_len); - if (fwc->calc_trans_crc != fwc->calc_partition_crc) { + if (crc32(0, buf, calc_len) != crc32(0, rdbuf, calc_len)) { pr_err("calc_len:%d\n", calc_len); pr_err("crc err at trans len %u\n", fwc->trans_size); - pr_err("trans crc:0x%x, partition crc:0x%x\n", - fwc->calc_trans_crc, fwc->calc_partition_crc); } #endif debug("%s, data len %d, trans len %d, calc len %d\n", __func__, len, fwc->trans_size, calc_len); - free(rdbuf); + if (rdbuf) + free(rdbuf); return len; } @@ -1130,11 +1144,23 @@ static s32 nand_fwc_ubi_writer(struct fwc_info *fwc, u8 *buf, s32 len) { struct aicupg_nand_priv *priv; struct ubi_volume *vol; - s32 ret, i; + s32 calc_len, ret, i; priv = (struct aicupg_nand_priv *)fwc->priv; if (!priv) return 0; + + if ((fwc->meta.size - fwc->trans_size) < len) + calc_len = fwc->meta.size - fwc->trans_size; + else + calc_len = len; + + fwc->calc_partition_crc = crc32(fwc->calc_partition_crc, buf, calc_len); + +#ifdef CONFIG_AICUPG_FIRMWARE_SECURITY + firmware_security_decrypt(buf, len); +#endif + for (i = 0; i < MAX_DUPLICATED_PART; i++) { if (!priv->vols[i]) continue; @@ -1146,7 +1172,6 @@ static s32 nand_fwc_ubi_writer(struct fwc_info *fwc, u8 *buf, s32 len) } } - fwc->calc_partition_crc = fwc->meta.crc; /* TODO: need to calc CRC */ return len; } diff --git a/source/uboot-2021.10/drivers/aicupg/nand_fwc_spl.c b/source/uboot-2021.10/drivers/aicupg/nand_fwc_spl.c index dbd53beaa..70156685f 100644 --- a/source/uboot-2021.10/drivers/aicupg/nand_fwc_spl.c +++ b/source/uboot-2021.10/drivers/aicupg/nand_fwc_spl.c @@ -17,6 +17,7 @@ #include "nand_fwc_spl.h" #include "spi_enc_spl.h" #include +#include struct aicupg_nand_spl { struct mtd_info *mtd; @@ -419,20 +420,32 @@ static s32 nand_fwc_spl_program(struct fwc_info *fwc, u32 data_size, blkidx, blkcnt, pa, pgidx, slice_size; size_t retlen; loff_t offs; - s32 ret = -1, i, calc_len; - u32 trans_crc; - u32 partition_crc; + s32 ret = -1, i; u32 trans_size; u32 page_per_blk; + fwc->calc_partition_crc = crc32(fwc->calc_partition_crc, spl->image_buf, fwc->meta.size); +#ifdef CONFIG_AICUPG_FIRMWARE_SECURITY + firmware_security_decrypt(spl->image_buf, spl->rx_size); +#endif + pt = malloc(PAGE_TABLE_USE_SIZE); page_data = malloc(PAGE_MAX_SIZE); - rd_page_data = malloc(PAGE_MAX_SIZE); - if (!page_data || !rd_page_data || !pt) { - ret = -1; + if (!page_data) { + pr_err("malloc page_data failed.\n"); + ret = -ENOMEM; goto out; } +#ifdef CONFIG_AICUPG_SINGLE_TRANS_BURN_CRC32_VERIFY + rd_page_data = malloc(PAGE_MAX_SIZE); + if (!rd_page_data || !pt) { + pr_err("malloc rd_page_data failed.\n"); + ret = -ENOMEM; + goto out; + } +#endif + ret = spl_build_page_table(spl, pt); if (ret) { pr_err("Generate page table failed.\n"); @@ -482,8 +495,6 @@ static s32 nand_fwc_spl_program(struct fwc_info *fwc, } /* Write image data to page */ - trans_crc = 0; - partition_crc = 0; trans_size = 0; p = spl->image_buf; end = p + spl->buf_size; @@ -512,6 +523,7 @@ static s32 nand_fwc_spl_program(struct fwc_info *fwc, ret = -1; goto out; } +#ifdef CONFIG_AICUPG_SINGLE_TRANS_BURN_CRC32_VERIFY // Read data to calc crc ret = mtd_read(spl->mtd, offs, slice_size, &retlen, rd_page_data); @@ -521,19 +533,9 @@ static s32 nand_fwc_spl_program(struct fwc_info *fwc, goto out; } - if ((trans_size + data_size) > fwc->meta.size) - calc_len = fwc->meta.size % slice_size; - else - calc_len = slice_size; - - partition_crc = crc32(partition_crc, rd_page_data, calc_len); -#ifdef CONFIG_AICUPG_SINGLE_TRANS_BURN_CRC32_VERIFY - trans_crc = crc32(trans_crc, page_data, calc_len); - if (trans_crc != partition_crc) { - pr_err("calc_len:%d\n", calc_len); + if (crc32(0, page_data, slice_size) != crc32(0, rd_page_data, slice_size)) { + pr_err("calc_len:%d\n", slice_size); pr_err("crc err at trans len %u\n", trans_size); - pr_err("trans crc:0x%x, partition crc:0x%x\n", - trans_crc, partition_crc); ret = -1; goto out; } @@ -541,8 +543,6 @@ static s32 nand_fwc_spl_program(struct fwc_info *fwc, trans_size += data_size; } - fwc->calc_partition_crc = partition_crc; - fwc->calc_trans_crc = trans_crc; out: if (page_data) free(page_data); diff --git a/source/uboot-2021.10/drivers/aicupg/nor_fwc.c b/source/uboot-2021.10/drivers/aicupg/nor_fwc.c index c3093127c..5603ff59c 100644 --- a/source/uboot-2021.10/drivers/aicupg/nor_fwc.c +++ b/source/uboot-2021.10/drivers/aicupg/nor_fwc.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "spi_enc_spl.h" @@ -208,6 +209,9 @@ void nor_fwc_start(struct fwc_info *fwc) #endif fwc->block_size = mtd->writesize; debug("%s, FWC name %s\n", __func__, fwc->meta.name); +#ifdef CONFIG_AICUPG_FIRMWARE_SECURITY + firmware_security_init(); +#endif return; err: pr_err("error:free(priv)\n"); @@ -235,6 +239,17 @@ s32 nor_fwc_data_write(struct fwc_info *fwc, u8 *buf, s32 len) if (!priv) return 0; + if ((fwc->meta.size - fwc->trans_size) < len) + calc_len = fwc->meta.size - fwc->trans_size; + else + calc_len = len; + + fwc->calc_partition_crc = crc32(fwc->calc_partition_crc, buf, calc_len); + +#ifdef CONFIG_AICUPG_FIRMWARE_SECURITY + firmware_security_decrypt(buf, len); +#endif + for (i = 0; i < MAX_DUPLICATED_PART; i++) { mtd = priv->mtds[i]; if (!mtd) @@ -299,19 +314,10 @@ s32 nor_fwc_data_write(struct fwc_info *fwc, u8 *buf, s32 len) priv->offs[i] = offset + retlen; } - if ((fwc->meta.size - fwc->trans_size) < len) - calc_len = fwc->meta.size - fwc->trans_size; - else - calc_len = len; - - fwc->calc_partition_crc = crc32(fwc->calc_partition_crc, rdbuf, calc_len); #ifdef CONFIG_AICUPG_SINGLE_TRANS_BURN_CRC32_VERIFY - fwc->calc_trans_crc = crc32(fwc->calc_trans_crc, buf, calc_len); - if (fwc->calc_trans_crc != fwc->calc_partition_crc) { + if (crc32(0, buf, calc_len) != crc32(0, rdbuf, calc_len)) { pr_err("calc_len:%d\n", calc_len); pr_err("crc err at trans len %u\n", fwc->trans_size); - pr_err("trans crc:0x%x, partition crc:0x%x\n", - fwc->calc_trans_crc, fwc->calc_partition_crc); } #endif fwc->trans_size += len; diff --git a/source/uboot-2021.10/drivers/misc/Kconfig b/source/uboot-2021.10/drivers/misc/Kconfig index 16101e834..448a340d8 100644 --- a/source/uboot-2021.10/drivers/misc/Kconfig +++ b/source/uboot-2021.10/drivers/misc/Kconfig @@ -61,6 +61,25 @@ config ARTINCHIP_SID help Enable support for ArtInChip eFuse read/write. +config ARTINCHIP_SID_BURN_SPIENC_KEY_CMD + bool "Enable SID(eFuse) burn spienc key command" + depends on ARTINCHIP_SID + default n + help + Burn spienc related eFuse. + +if ARTINCHIP_SID_BURN_SPIENC_KEY_CMD + +config ARTINCHIP_SID_BURN_SIMULATED + bool "Enable SID(eFuse) simulated burning" + default n + +config ARTINCHIP_SID_CONTINUE_BOOT_BURN_AFTER + bool "Enable SID(eFuse) continue to boot after burning" + default n + +endif + config ARTINCHIP_SYSCFG bool "Syscfg driver for ArtInChip SoC" depends on MISC diff --git a/source/uboot-2021.10/include/artinchip/firmware_security.h b/source/uboot-2021.10/include/artinchip/firmware_security.h new file mode 100644 index 000000000..09fe99568 --- /dev/null +++ b/source/uboot-2021.10/include/artinchip/firmware_security.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2025, ArtInChip Technology Co., Ltd + */ +#ifndef __FIRMWARE_SECURITY_H_ +#define __FIRMWARE_SECURITY_H_ + +#include +#include + +int firmware_security_init(void); +void firmware_security_decrypt(uint8_t *buf, unsigned int length); + +#endif // __FIRMWARE_SECURITY_H_ diff --git a/target/d211/common/d211.pbp b/target/d211/common/d211.pbp index dea6292cf..16128a027 100644 Binary files a/target/d211/common/d211.pbp and b/target/d211/common/d211.pbp differ diff --git a/target/d211/common/libfirmware_security.a b/target/d211/common/libfirmware_security.a new file mode 100644 index 000000000..b5d5ae127 Binary files /dev/null and b/target/d211/common/libfirmware_security.a differ diff --git a/target/d211/demo88_nand/keys/.gitignore b/target/d211/demo88_nand/keys/.gitignore new file mode 100644 index 000000000..bf1eadbaa --- /dev/null +++ b/target/d211/demo88_nand/keys/.gitignore @@ -0,0 +1,3 @@ +rotpk* +*.h +*.pem diff --git a/target/d211/demo88_nand/keys/gen_spienc_key.sh b/target/d211/demo88_nand/keys/gen_spienc_key.sh new file mode 100755 index 000000000..96ee838ca --- /dev/null +++ b/target/d211/demo88_nand/keys/gen_spienc_key.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# +# Copyright (c) 2022-2025, ArtInChip Technology Co., Ltd +# +# SPDX-License-Identifier: Apache-2.0 +# +# Authors: Xiong Hao +# + +if [ ! -f "rsa_private_key.der" ] || [ ! -f "rsa_public_key.der" ];then + openssl genrsa -out rsa_private_key.pem 2048 + openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem + openssl base64 -d -in rsa_public_key.pem -out rsa_public_key.der + openssl base64 -d -in rsa_private_key.pem -out rsa_private_key.der +fi + +if [ ! -f "set_aes_key.txt" ] || [ ! -f "set_nonce.txt" ];then + openssl rand -hex 16 > set_aes_key.txt + openssl rand -hex 8 > set_nonce.txt +fi + +openssl dgst -md5 -binary -out rotpk.bin rsa_public_key.der + +xxd -p -r set_aes_key.txt > spi_aes.key +xxd -p -r set_nonce.txt > spi_nonce.key +xxd -c 16 -i spi_aes.key > spi_aes_key.h +xxd -c 16 -i spi_nonce.key >> spi_aes_key.h +xxd -c 16 -i rotpk.bin >> spi_aes_key.h + +cp spi_aes_key.h ../../../../source/uboot-2021.10/board/artinchip/d211/spi_aes_key.h +cp ../../common/libfirmware_security.a ../../../../source/uboot-2021.10/drivers/aicupg/libfirmware_security.a diff --git a/target/d211/demo88_nand/keys/set_aes_key.txt b/target/d211/demo88_nand/keys/set_aes_key.txt new file mode 100644 index 000000000..a965e715f --- /dev/null +++ b/target/d211/demo88_nand/keys/set_aes_key.txt @@ -0,0 +1 @@ +00000000000000000000000000000000 diff --git a/target/d211/demo88_nand/keys/set_nonce.txt b/target/d211/demo88_nand/keys/set_nonce.txt new file mode 100644 index 000000000..baa82f2af --- /dev/null +++ b/target/d211/demo88_nand/keys/set_nonce.txt @@ -0,0 +1 @@ +0000000000000000 diff --git a/tools/scripts/firmware_security_encrypt b/tools/scripts/firmware_security_encrypt new file mode 100755 index 000000000..4b1939c55 Binary files /dev/null and b/tools/scripts/firmware_security_encrypt differ diff --git a/tools/scripts/firmware_security_encrypt.exe b/tools/scripts/firmware_security_encrypt.exe new file mode 100755 index 000000000..63d5e0134 Binary files /dev/null and b/tools/scripts/firmware_security_encrypt.exe differ diff --git a/tools/scripts/mk_image.py b/tools/scripts/mk_image.py index 970e2ccca..5aca78f68 100755 --- a/tools/scripts/mk_image.py +++ b/tools/scripts/mk_image.py @@ -12,6 +12,7 @@ import math import zlib import json import struct +import shutil import argparse import platform import subprocess @@ -1105,6 +1106,10 @@ def aic_boot_create_image_v2(cfg, keydir, datadir): else: signature_bytes = aic_boot_gen_signature_bytes(cfg, bootimg) bootimg = bootimg + signature_bytes + if aic_boot_with_ext_loader(cfg): + padlen = round_up(len(bootimg), META_ALIGNED_SIZE) - len(bootimg) + if padlen > 0: + bootimg += bytearray(padlen) return bootimg # Secure boot is not enabled, always add md5 result to the end @@ -1175,6 +1180,58 @@ def spienc_create_image(imgcfg, script_dir): sys.exit(1) +def get_align_file(filename, alignsize): + if os.path.exists(filename) is False: + print("File {} is not exist".format(filename)) + sys.exit(1) + + filesize = os.path.getsize(filename) + padlen = (alignsize - (filesize % alignsize)) % alignsize + + alignfile = filename + '.align' + shutil.copyfile(filename, alignfile) + + if padlen == 0: + return alignfile + + with open(alignfile, "ab") as f: + f.write(bytearray(padlen)) + + return alignfile + + +def data_crypt_create_image(imgcfg, script_dir): + keypath = get_file_path(imgcfg["key"], imgcfg["keydir"]) + if keypath is None: + keypath = get_file_path(imgcfg["key"], imgcfg["datadir"]) + + mkcmd = os.path.join(script_dir, "firmware_security_encrypt") + if os.path.exists(mkcmd) is False: + mkcmd = "firmware_security_encrypt" + if sys.platform == "win32": + mkcmd += ".exe" + cmd = [mkcmd] + cmd.append("--key") + cmd.append("{}".format(keypath)) + if "nonce" in imgcfg: + noncepath = get_file_path(imgcfg["nonce"], imgcfg["keydir"]) + if noncepath is None: + noncepath = get_file_path(imgcfg["nonce"], imgcfg["datadir"]) + cmd.append("--nonce") + cmd.append("{}".format(noncepath)) + if "tweak" in imgcfg: + cmd.append("--tweak") + cmd.append("{}".format(imgcfg["tweak"])) + cmd.append("--infile") + cmd.append("{}".format(get_align_file(imgcfg["input"], 16))) + cmd.append("--outfile") + cmd.append("{}".format(imgcfg["output"])) + ret = subprocess.run(cmd, stdout=subprocess.PIPE) + if ret.returncode != 0: + print(ret.stdout.decode("utf-8")) + sys.exit(1) + + def concatenate_create_image(outname, flist, datadir): with open(outname, "wb") as fout: for fn in flist: @@ -1775,6 +1832,7 @@ def img_write_fwc_file_to_binfile(binfile, cfg, datadir): start_block = 0 last_block = 0 used_block = 0 + total_block = 0 if VERBOSE: print("\tPacking file data:") @@ -1807,7 +1865,16 @@ def img_write_fwc_file_to_binfile(binfile, cfg, datadir): used_block = filesize // block_size // 1024 + 1 else: used_block = filesize // block_size // 1024 - last_block = start_block + used_block - 1 + total_block = (part_size // block_size // 1024) + if (total_block - used_block) <= (total_block // 50): + print("\t\tPart {} reserved blocks are less than 2%, \ + bad blocks may cause burning failures".format(part_name)) + + last_block = start_block + total_block - 1 + if last_block < (start_block + used_block - 1): + print("\t\tFile {} exceeds the part {} size".format(path, part_name)) + sys.exit(1) + elif cfg["image"]["info"]["media"]["type"] == "spi-nor": block_size = 64 start_block = part_offset // block_size // 1024 @@ -2338,6 +2405,60 @@ def firmware_component_preproc_spienc(cfg, datadir, keydir, bindir): spienc_create_image(imgcfg, bindir) +def firmware_component_preproc_data_crypt(cfg, datadir, keydir, bindir): + preproc_cfg = get_pre_process_cfg(cfg) + imgnames = preproc_cfg["data_crypt"].keys() + for name in imgnames: + imgcfg = preproc_cfg["data_crypt"][name] + imgcfg["keydir"] = keydir + imgcfg["datadir"] = datadir + inname = datadir + imgcfg["file"] + outname = datadir + name + imgcfg["input"] = inname + imgcfg["output"] = outname + + imglist = [] + if cfg["image"]["info"]["media"]["type"] == "spi-nand": + imglist = [] + orglist = cfg["image"]["info"]["media"]["array_organization"] + for item in orglist: + paramstr = "_page_{}_block_{}".format(item["page"], item["block"]) + paramstr = paramstr.lower() + status_ok = True + if not inname.endswith(".ubi") and not inname.endswith(".ubifs"): + continue + + if inname.find("*") <= 0: + # No need to check + continue + + imgcfg["output"] = outname.replace("*", paramstr) + imgcfg["input"] = inname.replace("*", paramstr) + imgcfg["input"] = get_file_path(imgcfg["input"], datadir) + if imgcfg["input"] is None: + status_ok = False + print("{} is not found".format(inname)) + continue + + if status_ok: + imglist.append(paramstr) + + if len(imglist) > 0: + for img in imglist: + imgcfg["input"] = inname.replace("*", paramstr) + imgcfg["output"] = outname.replace("*", paramstr) + if get_file_path(imgcfg["input"], datadir): + if VERBOSE: + print("\tCreating {} ...".format(imgcfg["output"])) + data_crypt_create_image(imgcfg, bindir) + else: + print("{} is not found".format(imgcfg["input"])) + else: + if VERBOSE: + print("\tCreating {} ...".format(outname)) + data_crypt_create_image(imgcfg, bindir) + + def firmware_component_preproc_concatenate(cfg, datadir, keydir, bindir): preproc_cfg = get_pre_process_cfg(cfg) imgnames = preproc_cfg["concatenate"].keys() @@ -2385,10 +2506,12 @@ def firmware_component_preproc(cfg, datadir, keydir, bindir): firmware_component_preproc_aicboot(cfg, datadir, keydir, bindir) if "aicimage" in preproc_cfg: firmware_component_preproc_aicimage(cfg, datadir, keydir, bindir) - if "spienc" in preproc_cfg: - firmware_component_preproc_spienc(cfg, datadir, keydir, bindir) if "concatenate" in preproc_cfg: firmware_component_preproc_concatenate(cfg, datadir, keydir, bindir) + if "spienc" in preproc_cfg: + firmware_component_preproc_spienc(cfg, datadir, keydir, bindir) + if "data_crypt" in preproc_cfg: + firmware_component_preproc_data_crypt(cfg, datadir, keydir, bindir) def generate_bootcfg(bcfgfile, cfg):