Meta-toradex-security with NAND

I want to leave few comments regarding this promising HAB/AHAB signing layer.

I managed to sign IMX7 u-boot-nand from Yocto with some mods. Issues I found:

  1. u-boot-nand padding at the end. Old u-boot .bb had padding tasks for NAND variants, log here suggests padding different way. And… signing layer of course doesn’t take it into account.

First of all why padding is required. ROM depending on fuses settings tries to boot different boot image instances. When ECC fatally fails, ROM tries to boot next boot image copy at different address and so on. If you write to NAND less data than specified in image BOOTDATA struct, ECC will fail and ROM will try the next image copy. When HAB is enabled, it increases image size in BOOTDATA by CONFIG_CSF_SIZE, which defaults at 0x2060, expecting signing process will add those 0x2060 bytes at the end. Usually it is smaller. So you either need to fix CONFIG_CSF_SIZE or pad at the end.

This breaks signing layer, because it cat’s signature at the end. So, we need to either unpad image, sign it, and pad again. Or dd into resulting image at CSF offset with conv=notrunc. Both could be fine with EMMC and NAND.

  1. Another issue is u-boot-hab.inc calls create_csf.sh with IMXBOOT=${UBOOT_BINARY}

u-boot-nand.imx is padded at start to 1k. So either csf whould should “checksum” at offset 1k or instead “checksum” u-boot.imx, which is the same unpadded. In both cases, EMMC and NAND for create_csf.sh could be the same u-boot.${UBOOT_SUFFIX}

This variant of u-boot-hab.inc sign_hab4() helps producing signed and bootable u-boot-nand.imx

sign_habv4() {
    if [ ! -e "${TDX_IMX_HAB_CST_BIN}" ]; then
        bberror "Could not find CST binary at ${TDX_IMX_HAB_CST_BIN}."
        exit 1
    fi

    for f in "${TDX_IMX_HAB_CST_SRK}" "${TDX_IMX_HAB_CST_CSF_CERT}" \
             "${TDX_IMX_HAB_CST_IMG_CERT}" "${TDX_IMX_HAB_CST_SRK_FUSE}"
    do
        if [ ! -e "${f}" ]; then
            bberror "Could not find cert file at ${f}."
            exit 1
        fi
    done

    local soc="$1"

    if [ -n "${UBOOT_CONFIG}" ]; then
        i=0
        j=0
        for config in ${UBOOT_MACHINE}; do
            i=$(expr $i + 1);
            for type in ${UBOOT_CONFIG}; do
                j=$(expr $j + 1);
                if [ $j -eq $i ]; then
		    # TODO: finish this when working on machines with an SPL
		    bbnote "Machines with UBOOT_CONFIG set, are not implemented yet."
                fi
            done
        done
    else
	if echo "${UBOOT_BINARY}" | grep -q "nand" ; then
	   # Generate CSF alwas refer u-boot-dtb.${UBOOT_SUFFIX} for EMMC and NAND
           TDX_IMX_HAB_CST_SRK="${TDX_IMX_HAB_CST_SRK}" \
           TDX_IMX_HAB_CST_CSF_CERT="${TDX_IMX_HAB_CST_CSF_CERT}" \
           TDX_IMX_HAB_CST_IMG_CERT="${TDX_IMX_HAB_CST_IMG_CERT}" \
           TDX_IMX_HAB_CST_BIN="${TDX_IMX_HAB_CST_BIN}" \
           IMXBOOT="${B}/u-boot.${UBOOT_SUFFIX}" \
           HAB_LOG="${B}/${UBOOT_MAKE_TARGET}.log" \
           ${WORKDIR}/create_csf.sh -m "${soc}"

	   # Save unsigned image
	   cp ${UBOOT_BINARY} ${UBOOT_BINARY}-unsigned

	   # determine unpadded size assuming IVT is @0x400 and BOOTDATA follows immediately IVT
	   tmp=$(mktemp)
	   # extract self pointer
	   dd if=${UBOOT_BINARY}  of=${tmp} bs=1 count=4 skip=1044
	   self=$(hexdump -e '"%u"' ${tmp})

	   # extract csf pointer
	   dd if=${UBOOT_BINARY}  of=$tmp bs=1 count=4 skip=1048
	   csf=$(hexdump -e '"%u"' $tmp)

	   unsignedsize=$(expr ${csf} - ${self} + 1024)
	
	   #copy CSF into image, which is already padded at both ends
	   dd of=${UBOOT_BINARY} if=${WORKDIR}/csf-uboot.bin seek=1 bs=$unsignedsize conv=notrunc
	else
           # Generate CSF file
           TDX_IMX_HAB_CST_SRK="${TDX_IMX_HAB_CST_SRK}" \
           TDX_IMX_HAB_CST_CSF_CERT="${TDX_IMX_HAB_CST_CSF_CERT}" \
           TDX_IMX_HAB_CST_IMG_CERT="${TDX_IMX_HAB_CST_IMG_CERT}" \
           TDX_IMX_HAB_CST_BIN="${TDX_IMX_HAB_CST_BIN}" \
           IMXBOOT="${B}/${UBOOT_BINARY}" \
           HAB_LOG="${B}/${UBOOT_MAKE_TARGET}.log" \
           ${WORKDIR}/create_csf.sh -m "${soc}"

	   # Save unsigned image
	   mv ${UBOOT_BINARY} ${UBOOT_BINARY}-unsigned

	   # Append CSF to image
	   cat ${UBOOT_BINARY}-unsigned ${WORKDIR}/csf-uboot.bin > ${UBOOT_BINARY}
	fi

	# Create fuse commands
	${WORKDIR}/create_fuse_cmds.sh ${soc} ${TDX_IMX_HAB_CST_SRK_FUSE} ${WORKDIR}/fuse-cmds.txt
    fi
}

Greetings @Edward,

At the moment meta-toradex-security is mostly focused towards the Torizon OS use case. This is why we haven’t done anything with NAND yet since those modules are not supported with Torizon.

That said the ideal goal of this layer should be a generic layer that can be used as such. Therefore we would appreciate any contributions even if it does not strictly align with our current goals.

That said, if you don’t mind could you open a PR for your work here. Then I can bring this up to the team for further review and consideration.

Best Regards,
Jeremias