Is there some odd initramfs limitation that requires explicitly calling out /usr/bin/busybox throughout the whole script?
Surely echo atleast can be relied on to be built into the shell or PATH. On Mon, Mar 2, 2026 at 12:07 PM Shiva Tripathi via lists.yoctoproject.org <[email protected]> wrote: > > Add ti-encrypted-boot-initramfs for LUKS encryption with TPM-sealed > keys. This provides full disk encryption using dm-crypt with keys > sealed by firmware TPM (fTPM) running in OP-TEE and stored in eMMC RPMB. > > The initramfs includes: > - Custom init script for in-place LUKS encryption on first boot > - TPM key sealing/unsealing using persistent handle 0x81080001 > - Support for cryptsetup, tpm2-tools, and OP-TEE client > - Automatic filesystem resize after encryption > > ti-encrypted-boot-initramfs builds when MACHINE_FEATURES contains > 'luks-encryption'. > > Signed-off-by: Shiva Tripathi <[email protected]> > --- > .../initramfs-ti-encrypted-init/files/init | 324 ++++++++++++++++++ > .../initramfs-ti-encrypted-init_1.0.bb | 30 ++ > .../initramfs/ti-encrypted-boot-initramfs.bb | 50 +++ > 3 files changed, 404 insertions(+) > create mode 100644 > meta-ti-bsp/recipes-ti/initramfs/initramfs-ti-encrypted-init/files/init > create mode 100644 > meta-ti-bsp/recipes-ti/initramfs/initramfs-ti-encrypted-init_1.0.bb > create mode 100644 > meta-ti-bsp/recipes-ti/initramfs/ti-encrypted-boot-initramfs.bb > > diff --git > a/meta-ti-bsp/recipes-ti/initramfs/initramfs-ti-encrypted-init/files/init > b/meta-ti-bsp/recipes-ti/initramfs/initramfs-ti-encrypted-init/files/init > new file mode 100644 > index 00000000..6675b6ed > --- /dev/null > +++ b/meta-ti-bsp/recipes-ti/initramfs/initramfs-ti-encrypted-init/files/init > @@ -0,0 +1,324 @@ > +#!/usr/bin/busybox sh > +# TI SDK initramfs init script with LUKS2 + fTPM encryption support > + > +# Mount essential filesystems > +/usr/bin/busybox echo "Initializing system..." > +/usr/bin/busybox mount -t proc proc /proc > +/usr/bin/busybox mount -t sysfs sysfs /sys > +/usr/bin/busybox mount -t devtmpfs devtmpfs /dev > + > +# Configuration > +BOOT_DEV="/dev/mmcblk1p1" # Boot partition (FAT, unencrypted) > +ROOT_DEV="/dev/mmcblk1p2" # Root partition (will be encrypted) > +CRYPT_NAME="root_crypt" > +CRYPT_DEV="/dev/mapper/${CRYPT_NAME}" > +BOOT_MNT="/boot_part" > +TPM_PRIMARY_CTX="/tmp/tpm_primary.ctx" > +TPM_KEY_PRIV="/tmp/tpm_key.priv" > +TPM_KEY_PUB="/tmp/tpm_key.pub" > +TPM_KEY_CTX="/tmp/tpm_key.ctx" > +TPM2_HANDLE="0x81080001" # TPM persistent handle for LUKS key > +ENCRYPTION_MARKER="${BOOT_MNT}/.encryption_in_progress" > + > +# Wait for MMC device to appear (up to 10 seconds) > +/usr/bin/busybox echo "Waiting for storage device..." > +for i in 1 2 3 4 5 6 7 8 9 10; do > + if [ -b "${ROOT_DEV}" ]; then > + break > + fi > + /usr/bin/busybox sleep 1 > +done > + > +# Check if root device exists > +if [ ! -b "${ROOT_DEV}" ]; then > + /usr/bin/busybox echo "ERROR: Storage device not found!" > + /usr/bin/busybox sh > +fi > + > +# Mount boot partition > +/usr/bin/busybox echo "Mounting boot partition..." > +/usr/bin/busybox mkdir -p "${BOOT_MNT}" > +if ! /usr/bin/busybox mount "${BOOT_DEV}" "${BOOT_MNT}"; then > + /usr/bin/busybox echo "ERROR: Failed to mount boot partition!" > + /usr/bin/busybox echo "Attempting standard boot..." > + /usr/bin/busybox mkdir -p /newroot > + /usr/bin/busybox mount "${ROOT_DEV}" /newroot > + exec /usr/sbin/switch_root /newroot /sbin/init > +fi > + > +# Initialize fTPM in OP-TEE > +/usr/bin/busybox echo "Initializing secure hardware(fTPM)..." > + > +# Start TEE supplicant (required for fTPM TA to work) > +if [ -x /usr/sbin/tee-supplicant ]; then > + /usr/sbin/tee-supplicant -d & > + TEE_SUPPLICANT_PID=$! > + /usr/bin/busybox sleep 5 > +else > + /usr/bin/busybox echo "Warning: Trusted execution environment not > available" > +fi > + > +# Load fTPM kernel module > +if ! /sbin/modprobe tpm_ftpm_tee; then > + /usr/bin/busybox echo "Warning: TPM module failed to load" > +fi > + > +# Wait for TPM device (up to 10 seconds) > +for i in 1 2 3 4 5 6 7 8 9 10; do > + if [ -c /dev/tpmrm0 ]; then > + break > + fi > + /usr/bin/busybox sleep 1 > +done > + > +# Check if TPM is available > +TPM_AVAILABLE=0 > +if [ -c /dev/tpmrm0 ]; then > + TPM_AVAILABLE=1 > + export TPM2TOOLS_TCTI="device:/dev/tpmrm0" > +else > + /usr/bin/busybox echo "Warning: fTPM not available - encryption will be > skipped" > + if [ -n "${TEE_SUPPLICANT_PID}" ]; then > + /usr/bin/busybox kill "${TEE_SUPPLICANT_PID}" 2>/dev/null > + fi > +fi > + > +# Function: Generate 32-byte random key using TPM RNG > +generate_random_key() { > + if [ $TPM_AVAILABLE -eq 1 ]; then > + /usr/bin/tpm2_getrandom --hex 32 > + else > + /usr/bin/busybox echo "ERROR: TPM not available for key generation" > + return 1 > + fi > +} > + > +# Function: Seal data with TPM and store in persistent handle > +tpm_seal_key() { > + local KEY_DATA="$1" > + > + if [ $TPM_AVAILABLE -eq 0 ]; then > + /usr/bin/busybox echo "ERROR: TPM not available for sealing" > + return 1 > + fi > + > + # Create primary key in owner hierarchy > + /usr/bin/tpm2_createprimary -C o -c "${TPM_PRIMARY_CTX}" -Q || return 1 > + > + # Create sealed object > + /usr/bin/busybox echo -n "${KEY_DATA}" | \ > + /usr/bin/tpm2_create -C "${TPM_PRIMARY_CTX}" \ > + -u "${TPM_KEY_PUB}" -r "${TPM_KEY_PRIV}" \ > + -i- -Q || return 1 > + > + # Load sealed object into TPM > + /usr/bin/tpm2_load -C "${TPM_PRIMARY_CTX}" \ > + -u "${TPM_KEY_PUB}" -r "${TPM_KEY_PRIV}" \ > + -c "${TPM_KEY_CTX}" -Q || return 1 > + > + # Make key persistent at handle (stored in TPM NV RAM - RPMB) > + /usr/bin/tpm2_evictcontrol -C o -c "${TPM_KEY_CTX}" "${TPM2_HANDLE}" || > return 1 > + > + return 0 > +} > + > +# Function: Unseal data from TPM persistent handle > +tpm_unseal_key() { > + if [ $TPM_AVAILABLE -eq 0 ]; then > + /usr/bin/busybox echo "ERROR: TPM not available for unsealing" >&2 > + return 1 > + fi > + > + # Check if persistent handle exists > + if ! /usr/bin/tpm2_getcap handles-persistent | grep -q "${TPM2_HANDLE}"; > then > + /usr/bin/busybox echo "ERROR: TPM persistent handle not found" >&2 > + return 1 > + fi > + > + # Unseal key directly from persistent handle > + /usr/bin/tpm2_unseal -c "${TPM2_HANDLE}" || return 1 > + > + return 0 > +} > + > +# Function: Perform in-place LUKS encryption (first boot) > +encrypt_root_filesystem() { > + /usr/bin/busybox echo "==========================================" > + /usr/bin/busybox echo "First boot: Encrypting root filesystem" > + /usr/bin/busybox echo "==========================================" > + > + # Set marker to track encryption progress > + /usr/bin/busybox touch "${ENCRYPTION_MARKER}" > + /usr/bin/busybox sync > + > + # Generate random encryption key using TPM RNG > + /usr/bin/busybox echo "Generating encryption key..." > + LUKS_KEY=$(generate_random_key) > + > + if [ -z "${LUKS_KEY}" ]; then > + /usr/bin/busybox echo "ERROR: Failed to generate encryption key" > + /usr/bin/busybox rm -f "${ENCRYPTION_MARKER}" > + return 1 > + fi > + > + # Seal key with TPM before encryption starts > + /usr/bin/busybox echo "Securing key with TPM..." > + if ! tpm_seal_key "${LUKS_KEY}"; then > + /usr/bin/busybox echo "ERROR: Failed to secure key" > + /usr/bin/busybox rm -f "${ENCRYPTION_MARKER}" > + return 1 > + fi > + > + # Filesystem check before encryption > + /usr/bin/busybox echo "Checking filesystem integrity..." > + /usr/sbin/e2fsck -f -y "${ROOT_DEV}" > + E2FSCK_RET=$? > + if [ ${E2FSCK_RET} -ge 4 ]; then > + /usr/bin/busybox echo "ERROR: Filesystem check failed" > + /usr/bin/busybox rm -f "${ENCRYPTION_MARKER}" > + return 1 > + fi > + > + # Shrink filesystem before encryption to leave room for LUKS header > + /usr/bin/busybox echo "Preparing filesystem for encryption..." > + /usr/sbin/resize2fs "${ROOT_DEV}" 368M || { > + /usr/bin/busybox echo "ERROR: Failed to prepare filesystem" > + /usr/bin/busybox rm -f "${ENCRYPTION_MARKER}" > + return 1 > + } > + > + # Perform in-place encryption > + /usr/bin/busybox echo "==========================================" > + /usr/bin/busybox echo "Encrypting filesystem..." > + /usr/bin/busybox echo "This will take several minutes." > + /usr/bin/busybox echo "DO NOT POWER OFF THE DEVICE!" > + /usr/bin/busybox echo "==========================================" > + > + /usr/bin/busybox echo -n "${LUKS_KEY}" | \ > + /usr/sbin/cryptsetup reencrypt --encrypt \ > + --type luks2 \ > + --cipher aes-xts-plain64 \ > + --key-size 256 \ > + --hash sha256 \ > + --reduce-device-size 32M \ > + --key-file - \ > + "${ROOT_DEV}" || { > + /usr/bin/busybox echo "ERROR: Encryption failed" > + /usr/bin/busybox rm -f "${ENCRYPTION_MARKER}" > + return 1 > + } > + > + /usr/bin/busybox echo "==========================================" > + /usr/bin/busybox echo "Encryption completed successfully!" > + /usr/bin/busybox echo "==========================================" > + > + # Remove encryption marker > + /usr/bin/busybox rm -f "${ENCRYPTION_MARKER}" > + /usr/bin/busybox sync > + > + # Unlock the newly encrypted device > + /usr/bin/busybox echo "Activating encrypted filesystem..." > + /usr/bin/busybox echo -n "${LUKS_KEY}" | \ > + /usr/sbin/cryptsetup luksOpen "${ROOT_DEV}" "${CRYPT_NAME}" > --key-file - || { > + /usr/bin/busybox echo "ERROR: Failed to activate encrypted > filesystem" > + return 1 > + } > + > + # Resize filesystem to fit the encrypted device > + /usr/bin/busybox echo "Optimizing filesystem..." > + /usr/sbin/resize2fs -f "${CRYPT_DEV}" || { > + /usr/bin/busybox echo "ERROR: Failed to optimize filesystem" > + return 1 > + } > + > + # Verify filesystem after resize > + /usr/sbin/e2fsck -f -y "${CRYPT_DEV}" || { > + /usr/bin/busybox echo "WARNING: Filesystem verification had issues, > but continuing" > + } > + return 0 > +} > + > +# Function: Unlock encrypted root filesystem (subsequent boots) > +unlock_encrypted_root() { > + /usr/bin/busybox echo "Unlocking encrypted filesystem..." > + > + # Unseal key from TPM persistent handle > + LUKS_KEY=$(tpm_unseal_key) > + > + if [ -z "${LUKS_KEY}" ]; then > + /usr/bin/busybox echo "ERROR: Failed to retrieve encryption key from > TPM" > + /usr/bin/busybox echo "Attempting passphrase fallback..." > + > + # Try to unlock with passphrase (interactive) > + /usr/sbin/cryptsetup luksOpen "${ROOT_DEV}" "${CRYPT_NAME}" || { > + /usr/bin/busybox echo "ERROR: Failed to unlock encrypted > filesystem" > + /usr/bin/busybox sh > + } > + else > + # Unlock with unsealed key > + /usr/bin/busybox echo -n "${LUKS_KEY}" | \ > + /usr/sbin/cryptsetup luksOpen "${ROOT_DEV}" "${CRYPT_NAME}" > --key-file - || { > + /usr/bin/busybox echo "ERROR: Failed to unlock with TPM key" > + /usr/bin/busybox sh > + } > + fi > + > + /usr/bin/busybox echo "Encrypted filesystem unlocked" > +} > + > +# Main boot logic > +/usr/bin/busybox echo "Checking filesystem encryption status..." > + > +# Check if device is LUKS encrypted > +if /usr/sbin/cryptsetup isLuks "${ROOT_DEV}"; then > + /usr/bin/busybox echo "Filesystem is encrypted" > + unlock_encrypted_root > + MOUNT_DEV="${CRYPT_DEV}" > +else > + /usr/bin/busybox echo "Filesystem is not encrypted" > + > + # Check if encryption is enabled and TPM is available > + if [ $TPM_AVAILABLE -eq 1 ]; then > + # Check for encryption marker (resume interrupted encryption) > + if [ -f "${ENCRYPTION_MARKER}" ]; then > + /usr/bin/busybox echo "Resuming interrupted encryption..." > + if ! encrypt_root_filesystem; then > + /usr/bin/busybox echo "ERROR: Failed to resume encryption" > + /usr/bin/busybox echo "Booting without encryption..." > + MOUNT_DEV="${ROOT_DEV}" > + else > + MOUNT_DEV="${CRYPT_DEV}" > + fi > + else > + # First boot - perform encryption > + if encrypt_root_filesystem; then > + MOUNT_DEV="${CRYPT_DEV}" > + else > + /usr/bin/busybox echo "ERROR: Encryption failed - booting > without encryption" > + MOUNT_DEV="${ROOT_DEV}" > + fi > + fi > + else > + /usr/bin/busybox echo "TPM not available - skipping encryption" > + MOUNT_DEV="${ROOT_DEV}" > + fi > +fi > + > +# Unmount boot partition before switching root > +/usr/bin/busybox umount "${BOOT_MNT}" > + > +# Mount root filesystem (encrypted or unencrypted) > +/usr/bin/busybox echo "Mounting root filesystem..." > +/usr/bin/busybox mkdir -p /newroot > +/usr/bin/busybox mount "${MOUNT_DEV}" /newroot || { > + /usr/bin/busybox echo "ERROR: Failed to mount root filesystem!" > + /usr/bin/busybox sh > +} > + > +/usr/bin/busybox echo "Boot complete" > + > +# Clean up tmpfs > +/usr/bin/busybox rm -f "${TPM_PRIMARY_CTX}" "${TPM_KEY_PUB}" > "${TPM_KEY_PRIV}" "${TPM_KEY_CTX}" > + > +# Switch to real root > +exec /usr/sbin/switch_root /newroot /sbin/init > diff --git > a/meta-ti-bsp/recipes-ti/initramfs/initramfs-ti-encrypted-init_1.0.bb > b/meta-ti-bsp/recipes-ti/initramfs/initramfs-ti-encrypted-init_1.0.bb > new file mode 100644 > index 00000000..7da878f7 > --- /dev/null > +++ b/meta-ti-bsp/recipes-ti/initramfs/initramfs-ti-encrypted-init_1.0.bb > @@ -0,0 +1,30 @@ > +SUMMARY = "TI encrypted boot initramfs init script" > +DESCRIPTION = "Custom /init script for encrypted boot with fTPM + LUKS > support" > + > +LICENSE = "MIT" > +LIC_FILES_CHKSUM = > "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420" > + > +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}/files:" > +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" > + > +SRC_URI = "file://init" > + > +S = "${WORKDIR}/sources" > +UNPACKDIR = "${WORKDIR}" > + > +# This recipe must run in the initramfs context > +inherit allarch > + > +do_install() { > + # Install /init script to root of initramfs > + install -m 0755 ${UNPACKDIR}/init ${D}/init > +} > + > +# Package the /init file > +FILES:${PN} = "/init" > + > +# Runtime dependencies > +RDEPENDS:${PN} = "busybox cryptsetup tpm2-tools tpm2-tss optee-client > e2fsprogs-e2fsck e2fsprogs-resize2fs util-linux-blkid" > + > +# This package must be included in initramfs > +PACKAGE_ARCH = "${MACHINE_ARCH}" > diff --git a/meta-ti-bsp/recipes-ti/initramfs/ti-encrypted-boot-initramfs.bb > b/meta-ti-bsp/recipes-ti/initramfs/ti-encrypted-boot-initramfs.bb > new file mode 100644 > index 00000000..314499db > --- /dev/null > +++ b/meta-ti-bsp/recipes-ti/initramfs/ti-encrypted-boot-initramfs.bb > @@ -0,0 +1,50 @@ > +SUMMARY = "TI encrypted boot initramfs image" > + > +DESCRIPTION = "Minimal initramfs image with dm-crypt/fTPM support for > encrypted root filesystem. \ > +This initramfs provides LUKS encryption with TPM-sealed keys stored in RPMB." > + > +LICENSE = "MIT" > + > +# Only build this when luks-encryption feature is enabled > +COMPATIBLE_MACHINE = "null" > +COMPATIBLE_MACHINE:k3 = "${@bb.utils.contains('MACHINE_FEATURES', > 'luks-encryption', '.*', 'null', d)}" > + > +INITRAMFS_FSTYPES = "cpio.gz" > + > +IMAGE_NAME = "ti-encrypted-boot-initramfs" > + > +export IMAGE_BASENAME = "${IMAGE_NAME}" > + > +# Install our custom init script and dependencies > +PACKAGE_INSTALL = "\ > + initramfs-ti-encrypted-init \ > + busybox \ > + base-passwd \ > + kmod \ > + cryptsetup \ > + tpm2-tools \ > + tpm2-tss \ > + libtss2-tcti-device \ > + optee-client \ > + util-linux-blkid \ > + e2fsprogs-e2fsck \ > + e2fsprogs-resize2fs \ > + kernel-module-tpm-ftpm-tee \ > + ${ROOTFS_BOOTSTRAP_INSTALL} \ > +" > + > +# Ensure the initramfs only contains the bare minimum > +IMAGE_FEATURES = "" > +IMAGE_LINGUAS = "" > + > +# Exclude kernel image from initramfs > +PACKAGE_EXCLUDE = "kernel-image-*" > + > +IMAGE_FSTYPES = "${INITRAMFS_FSTYPES}" > +IMAGE_NAME_SUFFIX ?= "" > +IMAGE_ROOTFS_SIZE = "16384" > +IMAGE_ROOTFS_EXTRA_SPACE = "0" > + > +BAD_RECOMMENDATIONS += "busybox-syslog" > + > +inherit image > -- > 2.34.1 > > > > -- Jonathan Cormier Senior Software Engineer Office: 315.425.4045 x222 http://www.CriticalLink.com 6712 Brooklawn Parkway, Syracuse, NY 13211
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#19631): https://lists.yoctoproject.org/g/meta-ti/message/19631 Mute This Topic: https://lists.yoctoproject.org/mt/118097473/21656 Group Owner: [email protected] Unsubscribe: https://lists.yoctoproject.org/g/meta-ti/unsub [[email protected]] -=-=-=-=-=-=-=-=-=-=-=-
