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

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#19628): 
https://lists.yoctoproject.org/g/meta-ti/message/19628
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]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to