Edit online

生成量产固件

按照本节流程编译加密的量产固件。

Edit online

配置 U-Boot

  1. 进入 SDK 根目录:
    cd <SDK_ROOT>
  2. 在 SDK 根目录,执行下列命令应用一个项目:

    示例如下:

    make d211_demo88_nand_defconfig
  3. 打开 U-Boot 的 menuconfig 菜单:
    make uboot-menuconfig
  4. 勾选或确认已勾选下列选项:
    ARTINCHIP_SPIENC
    AICUPG_FIRMWARE_SECURITY
    SPL_DRIVERS_MISC
    对应的配置界面如下:
    SPL / TPL  --->
        [*] Support misc drivers
    Device Drivers  --->
        [*]   Secure transfer firmware and burn
        Multifunction device drivers  --->
            [*] ArtInChip SPI Memory Encryption support
    注:
    编译量产固件时,务必将编译烧录 eFuse 程序时的代码修改还原。
  5. 在正式版本的固件中,建议删除下列功能选项同时禁用 U-Boot 控制台,防攻击者通过控制台读出 Flash 中的数据,否则可跳过此步。

    1. 删除下列功能选项:
      • CMD_MEMORY

      • CMD_MTD

      对应的配置界面如下:
      Command line interface  --->
          Memory commands  --->
              [ ] md, mm, nm, mw, cp, cmp, base, loop
          Device access commands  --->
              [ ] mtd
    2. target/d211/common/env.txt 文件中 bootdelay 设置为 -2,禁用 U-Boot 控制台。
Edit online

配置 Kernel

  1. 进入 SDK 根目录:
    cd <SDK_ROOT>
  2. 打开 Kernel 的 menuconfig 菜单:
    make kernel-menuconfig
  3. 在配置界面,勾选或确认已勾选下列参数:
    CRYPTO_DEV_ARTINCHIP_SPIENC
    参数对应的配置界面如下:
    -*- Cryptographic API  --->
        [*]   Hardware crypto devices  --->
            [*]   Support for artinchip cryptographic accelerator
            <*>     Artinchip's SPI Bus on-the-fly encryption driver
Edit online

配置 ITS

按照以下步骤配置和编译 U-Boot,并生成烧录固件。

  1. 在芯片级的 DTS 配置文件中使能 SPIENC 模块。
    spienc: spienc@18100000 {
        compatible = "artinchip,aic-spienc-v1.0";
        reg = <0x18100000 0x1000>;
        interrupts-extended = <&plic0 41 IRQ_TYPE_LEVEL_HIGH>;
        clocks = <&cmu CLK_SPIENC>;
        resets = <&rst RESET_SPIENC>;
        aic,spienc-tweak = <0>;
    };
    在板级的 DTS 配置文件 board.dts中,使能 SPIENC 模块。若要在 SPL 中使用 SPI_ENC,需设置标记 u-boot,dm-pre-reloc
    &spienc {
         aic,spienc-tweak = <0>;
         status = "okay";
         u-boot,dm-pre-reloc;
     };
  2. DTS 中的 aic,spienc-tweak 参数可以影响 COUNTER 的生成,进而改变加密的结果。修改该值,可以在不同产品的相同数据上获得不同的加密结果。此时,还需要配置下列参数,对具体的 SPI NAND / SPI NOR 设备使能加密:
    • aic,encrypt:标记该存储设备使能 SPI_ENC

    • aic,spi-id:设置当前存储设备所挂载的 SPI 控制器 ID

    board.dts 中的配置示例如下:
    &spi0 {
         pinctrl-names = "default";
         pinctrl-0 = <&spi0_pins_a>;
         status = "okay";
         u-boot,dm-pre-reloc;
         spi-flash@0 {
             #address-cells = <1>;
             #size-cells = <1>;
             compatible = "spi-nand";
             spi-max-frequency = <24000000>;
             spi-tx-bus-width = <1>;
             spi-rx-bus-width = <1>;
             reg = <0>;
             aic,encrypt;            // 标记该存储设备使能 SPI_ENC
             aic,spi-id = <0>;       // 设置当前存储设备所挂载的 SPI 控制器 ID
             status = "okay";
             u-boot,dm-pre-reloc;
         };
     };
  3. 在正式版本的固件中,建议禁用读写 Flash 和 Memory 相关的命令,同时禁用 U-Boot 控制台,防攻击者通过控制台读出 Flash 中的数据,否则可跳过此步。

    target/d211/common/env.txt 文件中 bootdelay 设置为 -2,禁用 U-Boot 控制台。

Edit online

固件签名加密

SDK/target/d211/demo88-nand/image_cfg.json 文件中进行下列配置,用于生成签名加密固件

  1. 配置生成签名的组件
    开启了安全启动后,需要对 U-Boot SPL 进行签名。参考签名相关部分的内容进行修改:
    {
        "spi-nand": {
            ...
        },
        "image": {
            ...
        },
        "info": { // Header information about image
            ...
        },
        "updater": { // Image writer which is downloaded to RAM by USB/UART
            ...
        },
        "target": { // Image components which will be burn to device's partitions
            ...
        },
        "pre-process": { // before v1.0.6 is the name "temporary"
            "aicimage": { // Create aic boot image
                "usbupg-ddr-init.aic": { // No loader, only PreBootProgram to initialize DDR
                    "head_ver": "0x00010001",
                    "resource": {
                        "private": "ddr_init.bin",
                        "pubkey": "keys/rsa_public_key.der",   // 签名相关
                        "pbp": "d211.pbp",
                    },
                    "signature": {
                         "algo": "rsa,2048",
                         "privkey": "keys/rsa_private_key.der",   // 签名相关
                    },
                },
                "pbp_ext.aic": {
                    "head_ver": "0x00010001",
                    "resource": {
                        "pbp": "d211.pbp",
                        "pubkey": "keys/rsa_public_key.der",   // 签名相关
                        "private": "pbp_cfg.bin",
                    },
                    "signature": {   // 签名相关
                         "algo": "rsa,2048",
                         "privkey": "keys/rsa_private_key.der",
                    },
                    // combine to use with loader.aic
                    "with_ext": "true",
                },
                "spl.aic": {
                    "head_ver": "0x00010001",
                    "loader": {
                        "file": "u-boot-spl-dtb.bin",
                        "load address": "0x42000000",
                        "entry point": "0x42000100", // 256 byte aic header
                    },
                    "resource": {
                        "private": "ddr_init.bin",
                        "pubkey": "keys/rsa_public_key.der",  // 签名相关
                    },
                    "signature": {  // 签名相关
                         "algo": "rsa,2048",
                         "privkey": "keys/rsa_private_key.der",
                    },
                },
            },
        },
    }
  2. 对组件进行加密

    image_cfg.json 的 “temporary” 或 “pre-process” 对象的最后,添加 “data_crypt” 对象配置。

    此处使用的 AES 加密密钥,即为生成密钥章节 中SDK/target/<soc>/<board>/pack/keys/ 文件目录生成的密钥。

    在下列示例中,配置了一组需要使用 “data_crypt” 工具进行加密的组件,其中生成u-boot-spl-dtb.aic.enc 组件的配置参数为:
    • algo: 加密的算法

    • file: 加密的源文件,此处为前面生成的 u-boot-spl-dtb.aic 文件

    • key: 使用的加密密钥

    • nonce: 使用的加密 Nonce 值

    • tweak: 该值不需要配置,保持为 0 即可

    {
        "spi-nand": {
            ...
        },
        "image": {
            ...
        },
        "info": { // Header information about image
            ...
        },
        "updater": { // Image writer which is downloaded to RAM by USB/UART
            ...
        },
        "target": { // Image components which will be burn to device's partitions
            ...
        },
        "pre-process": { // before v1.0.6 is the name "temporary"
            "data_crypt": {
                "u-boot-spl-dtb.aic.enc": { //加密 SPL 分区
                    "algo": "spienc-aes-128-ecb",
                    "file": "u-boot-spl-dtb.aic", // File to be encrypted
                    "key": "keys/spi_aes.key", // Keys the same in eFuse
                    "nonce": "keys/spi_nonce.key", // Nonce the same in eFuse
                    "tweak": "0",
                },
                "u-boot.itb.enc": { //加密 U-Boot 分区
                    "algo": "spienc-aes-128-ecb",
                    "file": "u-boot.itb", // File to be encrypted
                    "key": "keys/spi_aes.key", // Keys the same in eFuse
                    "nonce": "keys/spi_nonce.key", // Nonce the same in eFuse
                    "tweak": "0",
                },
                "env.bin.enc": { //加密 env 分区,备份分区使用同一个组件
                    "algo": "spienc-aes-128-ecb",
                    "file": "env.bin", // File to be encrypted
                    "key": "keys/spi_aes.key", // Keys the same in eFuse
                    "nonce": "keys/spi_nonce.key", // Nonce the same in eFuse
                    "tweak": "0",
                },
                "logo.itb.enc": { //加密 logo 分区
                    "algo": "spienc-aes-128-ecb",
                    "file": "logo.itb", // File to be encrypted
                    "key": "keys/spi_aes.key", // Keys the same in eFuse
                    "nonce": "keys/spi_nonce.key", // Nonce the same in eFuse
                    "tweak": "0",
                },
                "kernel.itb.enc": { //加密 kernel 分区
                    "algo": "spienc-aes-128-ecb",
                    "file": "kernel.itb", // File to be encrypted
                    "key": "keys/spi_aes.key", // Keys the same in eFuse
                    "nonce": "keys/spi_nonce.key", // Nonce the same in eFuse
                    "tweak": "0",
                },
                "recovery.itb.enc": { //加密 recovery 分区
                    "algo": "spienc-aes-128-ecb",
                    "file": "recovery.itb", // File to be encrypted
                    "key": "keys/spi_aes.key", // Keys the same in eFuse
                    "nonce": "keys/spi_nonce.key", // Nonce the same in eFuse
                    "tweak": "0",
                },
                "rootfs*.ubifs.enc": { //加密 rootfs 分区
                    "algo": "spienc-aes-128-ecb",
                    "file": "rootfs*.ubifs", // File to be encrypted
                    "key": "keys/spi_aes.key", // Keys the same in eFuse
                    "nonce": "keys/spi_nonce.key", // Nonce the same in eFuse
                    "tweak": "0",
                },
                ...
            },
        },
    }

    对于一个或者多个需要进行加密的组件,都应按照上述方式进行配置。

    mk_image.py 工具在读取 image_cfg.json 文件时,逐个处理放在 “data_crypt” 中的配置,生成对应的加密组件,然后再进行打包。

    重要:

    “data_crypt” 字段应放在 “temporary”/”pre-process” 的最后,因为处理 “data_crypt” 时,可能需要依赖前面配置生成的文件,比如 ”aicimage”。

  3. 配置烧录加密组件

    image_cfg.json 中配置下列参数,打包加密组件,以适配烧录加密固件的要求:

    1. updater 中打包的程序,应为非加密程序

      updater 中配置的参数,都不是 .enc 结尾的组件

    2. target 中打包的程序和数据,应为加密后的程序

      target 中配置的参数,都是 .enc 结尾的组件

    这是因为:
    • SD 卡启动时,首先运行 updater 中的程序,进入烧录模式。此时由于数据是从 SD 卡加载的,不能为加密程序,否则无法正常执行

    • target 中打包的程序是要烧录到 Flash 的数据,如果不加密,则无法起到保护的作用,因此需要打包加密后的组件

    {
        "spi-nand": { // Device, The name should be the same with string in image:info:media:type
            ...
        },
        "image": {
            ...
        },
        "info": { // Header information about image
            ...
        },
        "updater": { // Image writer which is downloaded to RAM by USB/UART
            "ddr": {
                "file": "usbupg-ddr-init.aic",
                "attr": ["required", "run"],
                "ram": "0x00103000"
            },
            "env": {
                "file": "env.bin",
                "attr": ["required"],
                "ram": "0x41000000"
            },
            "uboot": {
                "file": "u-boot.itb",
                "attr": ["required"],
                "ram": "0x41100000"
            },
            "logo": {
                "file": "logo.itb"
                "attr": ["required"],
                "ram": "0x42400000"
            },
            "spl": {
                "file": "u-boot-spl-dtb.aic",
                "attr": ["required", "run"],
                "ram": "0x40000000"
            },
        },
        "target": { // Image components which will be burn to device's partitions
            "spl": {
                "file": "u-boot-spl-dtb.aic.enc", //使用 enc 结尾的加密组件
                "attr": ["mtd", "required"],
                "part": ["spl"]
            },
            "uboot": {
                "file": "u-boot.itb.enc",   //使用 enc 结尾的加密组件
                "attr": ["mtd", "required"],
                "part": ["uboot"]
            },
            "env": {
                "file": "env.bin.enc", //使用 enc 结尾的加密组件
                "attr": ["mtd", "required"],
                "part": ["env","env_r"]
            },
            "logo": {
                "file": "logo.itb.enc", //使用 enc 结尾的加密组件
                "attr": ["mtd", "required"],
                "part": ["logo"]
            },
            "kernel": {
                "file": "kernel.itb.enc", //使用 enc 结尾的加密组件
                "attr": ["mtd", "required"],
                "part": ["kernel"]
            },
            "recovery": {
                "file": "recovery.itb.enc", //使用 enc 结尾的加密组件
                "attr": ["mtd", "required"],
                "part": ["recovery"]
            },
            "rootfs": {
                "file": rootfs*.ubifs.enc", //使用 enc 结尾的加密组件
                "attr": ["ubi", "required"],
                "part": ["ubiroot:rootfs"]
            },
        },
        "pre-process": { // before v1.0.6 is the name "temporary"
            ...
        },
    }
Edit online

USB 烧录

直接使用编译生成的 img 文件进行量产烧录即可。

Edit online

SD 卡量产

  • 标准方式

    编译生成下列文件后,将其复制到 SD 卡 FAT32 文件系统的根目录中,等待平台重新上电即可进入烧录:

    • bootcfg.txt

    • 打包后的 img 文件,例如d211_demo88_nand_page_2k_block_128k_v1.0.0.img
重要:

在修改 bootcfg.txt 文件后,确保使用 UNIX 格式的换行符,而非 DOS 格式的换行符,即 ‘\n’ 换行,而非 ‘\r\n’ 换行。