summaryrefslogtreecommitdiffstats
path: root/meta-ti-bsp
diff options
context:
space:
mode:
authorShiva Tripathi <s-tripathi1@ti.com>2026-03-26 14:26:22 +0530
committerRyan Eatmon <reatmon@ti.com>2026-03-26 09:40:56 -0500
commitbd0e3d7ba5be25d5e6cccc2f51b14fcf9f0bf817 (patch)
treeb1984dd8a370483895529ddb83d96d67a7003a22 /meta-ti-bsp
parent6f205ef07969510c266b700adcfb4ca457274a9e (diff)
downloadmeta-ti-bd0e3d7ba5be25d5e6cccc2f51b14fcf9f0bf817.tar.gz
initramfs-module-luks-ftpm: Add fTPM support
Add initramfs module to dynamic-layers/tpm-layer providing LUKS2 full disk encryption with TPM-sealed keys for TI K3 platforms. Keys are sealed by firmware TPM (fTPM) running in OP-TEE and stored in eMMC RPMB. Features: - First-boot in-place encryption with tpm2_getrandom key generation - TPM-sealed key storage via persistent handle 0x81080001 - Automatic unlock on subsequent boots - Space verification ensuring 32MB available for LUKS header The module is built only when meta-tpm layer is present and gets included in initramfs only when DISTRO_FEATURES='luks' and MACHINE_FEATURES='optee-ftpm' LUKS packages (cryptsetup, tpm2-tools, tpm2-tss, optee-ftpm, e2fsprogs-*) significantly increase initramfs size beyond the default 131072 limit. Increase INITRAMFS_MAXSIZE to 200000 to accommodate these packages. Signed-off-by: Shiva Tripathi <s-tripathi1@ti.com> Signed-off-by: Ryan Eatmon <reatmon@ti.com>
Diffstat (limited to 'meta-ti-bsp')
-rw-r--r--meta-ti-bsp/dynamic-layers/tpm-layer/recipes-ti/initramfs/initramfs-module-luks-ftpm/luksftpm341
-rw-r--r--meta-ti-bsp/dynamic-layers/tpm-layer/recipes-ti/initramfs/initramfs-module-luks-ftpm_1.0.bb43
-rw-r--r--meta-ti-bsp/dynamic-layers/tpm-layer/recipes-ti/initramfs/packagegroup-ti-core-initramfs.bbappend3
-rw-r--r--meta-ti-bsp/dynamic-layers/tpm-layer/recipes-ti/initramfs/ti-core-initramfs.bbappend1
4 files changed, 388 insertions, 0 deletions
diff --git a/meta-ti-bsp/dynamic-layers/tpm-layer/recipes-ti/initramfs/initramfs-module-luks-ftpm/luksftpm b/meta-ti-bsp/dynamic-layers/tpm-layer/recipes-ti/initramfs/initramfs-module-luks-ftpm/luksftpm
new file mode 100644
index 00000000..5e3aedc4
--- /dev/null
+++ b/meta-ti-bsp/dynamic-layers/tpm-layer/recipes-ti/initramfs/initramfs-module-luks-ftpm/luksftpm
@@ -0,0 +1,341 @@
1#!/bin/sh
2# initramfs-framework module for LUKS encryption with fTPM support
3
4# Configuration
5BOOT_DEV="/dev/mmcblk1p1" # Boot partition (FAT, unencrypted)
6ROOT_DEV="/dev/mmcblk1p2" # Root partition (will be encrypted)
7CRYPT_NAME="root_crypt"
8CRYPT_DEV="/dev/mapper/${CRYPT_NAME}"
9BOOT_MNT="/boot_part"
10TPM_PRIMARY_CTX="/tmp/tpm_primary.ctx"
11TPM_KEY_PRIV="/tmp/tpm_key.priv"
12TPM_KEY_PUB="/tmp/tpm_key.pub"
13TPM_KEY_CTX="/tmp/tpm_key.ctx"
14TPM2_HANDLE="0x81080001" # TPM persistent handle for LUKS key
15ENCRYPTION_MARKER="${BOOT_MNT}/.encryption_in_progress"
16
17# Wait for MMC device to appear
18wait_for_device() {
19 local device="$1"
20 local timeout="${2:-10}"
21
22 msg "Waiting for storage device ${device}..."
23 for i in $(seq 1 ${timeout}); do
24 if [ -b "${device}" ]; then
25 return 0
26 fi
27 sleep 1
28 done
29 return 1
30}
31
32# Initialize fTPM and check availability
33init_ftpm() {
34 msg "Initializing secure hardware (fTPM)..."
35
36 # Start TEE supplicant (required for fTPM TA to work)
37 if [ -x /usr/sbin/tee-supplicant ]; then
38 /usr/sbin/tee-supplicant -d &
39 TEE_SUPPLICANT_PID=$!
40 sleep 5
41 else
42 info "Warning: Trusted execution environment not available"
43 return 1
44 fi
45
46 # Load fTPM kernel module
47 if ! /sbin/modprobe tpm_ftpm_tee; then
48 info "Warning: TPM module failed to load"
49 return 1
50 fi
51
52 # Wait for TPM device
53 for i in $(seq 1 10); do
54 if [ -c /dev/tpmrm0 ]; then
55 export TPM2TOOLS_TCTI="device:/dev/tpmrm0"
56 return 0
57 fi
58 sleep 1
59 done
60
61 info "Warning: fTPM not available - encryption will be skipped"
62 return 1
63}
64
65# Generate 32-byte random key using TPM RNG
66generate_random_key() {
67 /usr/bin/tpm2_getrandom --hex 32
68}
69
70# Seal data with TPM and store in persistent handle
71tpm_seal_key() {
72 local KEY_DATA="$1"
73
74 # Create primary key in owner hierarchy
75 /usr/bin/tpm2_createprimary -C o -c "${TPM_PRIMARY_CTX}" -Q || return 1
76
77 # Create sealed object
78 echo -n "${KEY_DATA}" | \
79 /usr/bin/tpm2_create -C "${TPM_PRIMARY_CTX}" \
80 -u "${TPM_KEY_PUB}" -r "${TPM_KEY_PRIV}" \
81 -i- -Q || return 1
82
83 # Load sealed object into TPM
84 /usr/bin/tpm2_load -C "${TPM_PRIMARY_CTX}" \
85 -u "${TPM_KEY_PUB}" -r "${TPM_KEY_PRIV}" \
86 -c "${TPM_KEY_CTX}" -Q || return 1
87
88 # Make key persistent at handle (stored in TPM NV RAM - RPMB)
89 /usr/bin/tpm2_evictcontrol -C o -c "${TPM_KEY_CTX}" "${TPM2_HANDLE}" || return 1
90
91 return 0
92}
93
94# Unseal data from TPM persistent handle
95tpm_unseal_key() {
96 # Check if persistent handle exists
97 if ! /usr/bin/tpm2_getcap handles-persistent | grep -q "${TPM2_HANDLE}"; then
98 debug "ERROR: TPM persistent handle not found"
99 return 1
100 fi
101
102 # Unseal key directly from persistent handle
103 /usr/bin/tpm2_unseal -c "${TPM2_HANDLE}" || return 1
104
105 return 0
106}
107
108# Perform in-place LUKS encryption (first boot)
109encrypt_root_filesystem() {
110 msg "=========================================="
111 msg "First boot: Encrypting root filesystem"
112 msg "=========================================="
113
114 # Set marker to track encryption progress
115 touch "${ENCRYPTION_MARKER}"
116 sync
117
118 # Generate random encryption key using TPM RNG
119 msg "Generating encryption key..."
120 LUKS_KEY=$(generate_random_key)
121
122 if [ -z "${LUKS_KEY}" ]; then
123 msg "ERROR: Failed to generate encryption key"
124 rm -f "${ENCRYPTION_MARKER}"
125 return 1
126 fi
127
128 # Seal key with TPM before encryption starts
129 msg "Securing key with TPM..."
130 if ! tpm_seal_key "${LUKS_KEY}"; then
131 msg "ERROR: Failed to secure key"
132 rm -f "${ENCRYPTION_MARKER}"
133 return 1
134 fi
135
136 # Filesystem check before encryption
137 msg "Checking filesystem integrity..."
138 /usr/sbin/e2fsck -f -y "${ROOT_DEV}"
139 E2FSCK_RET=$?
140 if [ ${E2FSCK_RET} -ge 4 ]; then
141 msg "ERROR: Filesystem check failed"
142 rm -f "${ENCRYPTION_MARKER}"
143 return 1
144 fi
145
146 # Shrink filesystem before encryption to leave room for LUKS header
147 msg "Preparing filesystem for encryption..."
148 /usr/sbin/resize2fs -M "${ROOT_DEV}" || {
149 msg "ERROR: Failed to prepare filesystem"
150 rm -f "${ENCRYPTION_MARKER}"
151 return 1
152 }
153
154 # Verify partition has sufficient space for LUKS header
155 msg "Verifying space for encryption..."
156 MIN_BLOCKS=$(/usr/sbin/resize2fs -P "${ROOT_DEV}" 2>&1 | awk '/[Mm]inimum.*:/ {print $NF}')
157
158 # Get filesystem block size and device size
159 BLOCK_SIZE=$(/usr/sbin/tune2fs -l "${ROOT_DEV}" 2>/dev/null | awk '/^Block size:/ {print $NF}')
160 DEV_NAME=$(basename "${ROOT_DEV}")
161 PART_SECTORS=$(cat /sys/class/block/"${DEV_NAME}"/size 2>/dev/null)
162
163 if [ -z "${MIN_BLOCKS}" ] || [ -z "${BLOCK_SIZE}" ] || [ -z "${PART_SECTORS}" ]; then
164 msg "ERROR: Unable to determine partition geometry"
165 rm -f "${ENCRYPTION_MARKER}"
166 return 1
167 fi
168
169 # Convert filesystem blocks to 512-byte sectors
170 MIN_SECTORS=$((MIN_BLOCKS * BLOCK_SIZE / 512))
171 LUKS_SECTORS=65536 # 32MB in 512-byte sectors
172
173 if [ $((PART_SECTORS - MIN_SECTORS)) -lt ${LUKS_SECTORS} ]; then
174 msg "ERROR: Insufficient space for LUKS header (need 32MB free)"
175 rm -f "${ENCRYPTION_MARKER}"
176 return 1
177 fi
178
179 # Perform in-place encryption
180 msg "=========================================="
181 msg "Encrypting filesystem..."
182 msg "This will take several minutes."
183 msg "DO NOT POWER OFF THE DEVICE!"
184 msg "=========================================="
185
186 echo -n "${LUKS_KEY}" | \
187 /usr/sbin/cryptsetup reencrypt --encrypt \
188 --type luks2 \
189 --cipher aes-xts-plain64 \
190 --key-size 256 \
191 --hash sha256 \
192 --reduce-device-size 32M \
193 --key-file - \
194 "${ROOT_DEV}" || {
195 msg "ERROR: Encryption failed"
196 rm -f "${ENCRYPTION_MARKER}"
197 return 1
198 }
199
200 msg "=========================================="
201 msg "Encryption completed successfully!"
202 msg "=========================================="
203
204 # Remove encryption marker
205 rm -f "${ENCRYPTION_MARKER}"
206 sync
207
208 # Unlock the newly encrypted device
209 msg "Activating encrypted filesystem..."
210 echo -n "${LUKS_KEY}" | \
211 /usr/sbin/cryptsetup luksOpen "${ROOT_DEV}" "${CRYPT_NAME}" --key-file - || {
212 msg "ERROR: Failed to activate encrypted filesystem"
213 return 1
214 }
215
216 # Resize filesystem to fit the encrypted device
217 msg "Optimizing filesystem..."
218 /usr/sbin/resize2fs -f "${CRYPT_DEV}" || {
219 msg "ERROR: Failed to optimize filesystem"
220 return 1
221 }
222
223 # Verify filesystem after resize
224 /usr/sbin/e2fsck -f -y "${CRYPT_DEV}" || {
225 info "WARNING: Filesystem verification had issues, but continuing"
226 }
227
228 return 0
229}
230
231# Unlock encrypted root filesystem (subsequent boots)
232unlock_encrypted_root() {
233 msg "Unlocking encrypted filesystem..."
234
235 # Unseal key from TPM persistent handle
236 LUKS_KEY=$(tpm_unseal_key)
237
238 if [ -z "${LUKS_KEY}" ]; then
239 msg "ERROR: Failed to retrieve encryption key from TPM"
240 msg "Attempting passphrase fallback..."
241
242 # Try to unlock with passphrase (interactive)
243 /usr/sbin/cryptsetup luksOpen "${ROOT_DEV}" "${CRYPT_NAME}" || {
244 fatal "ERROR: Failed to unlock encrypted filesystem"
245 }
246 else
247 # Unlock with unsealed key
248 echo -n "${LUKS_KEY}" | \
249 /usr/sbin/cryptsetup luksOpen "${ROOT_DEV}" "${CRYPT_NAME}" --key-file - || {
250 fatal "ERROR: Failed to unlock with TPM key"
251 }
252 fi
253
254 msg "Encrypted filesystem unlocked"
255}
256
257# Module enabled check
258luksftpm_enabled() {
259 # Always run this module - it handles both encrypted and unencrypted cases
260 return 0
261}
262
263# Module main function
264luksftpm_run() {
265 # Wait for storage device
266 if ! wait_for_device "${ROOT_DEV}" 10; then
267 info "Storage device not found, skipping encryption module"
268 return 0
269 fi
270
271 # Mount boot partition
272 msg "Mounting boot partition..."
273 mkdir -p "${BOOT_MNT}"
274 if ! mount "${BOOT_DEV}" "${BOOT_MNT}"; then
275 info "ERROR: Failed to mount boot partition, attempting standard boot..."
276 mkdir -p ${ROOTFS_DIR}
277 mount "${ROOT_DEV}" ${ROOTFS_DIR}
278 return 0
279 fi
280
281 # Initialize fTPM
282 TPM_AVAILABLE=0
283 if init_ftpm; then
284 TPM_AVAILABLE=1
285 fi
286
287 # Check filesystem encryption status
288 msg "Checking filesystem encryption status..."
289
290 MOUNT_DEV="${ROOT_DEV}"
291
292 if /usr/sbin/cryptsetup isLuks "${ROOT_DEV}"; then
293 msg "Filesystem is encrypted"
294 unlock_encrypted_root
295 MOUNT_DEV="${CRYPT_DEV}"
296 else
297 msg "Filesystem is not encrypted"
298
299 # Check if encryption is enabled and TPM is available
300 if [ $TPM_AVAILABLE -eq 1 ]; then
301 # Check for encryption marker (resume interrupted encryption)
302 if [ -f "${ENCRYPTION_MARKER}" ]; then
303 msg "Resuming interrupted encryption..."
304 if ! encrypt_root_filesystem; then
305 msg "ERROR: Failed to resume encryption"
306 msg "Booting without encryption..."
307 MOUNT_DEV="${ROOT_DEV}"
308 else
309 MOUNT_DEV="${CRYPT_DEV}"
310 fi
311 else
312 # First boot - perform encryption
313 if encrypt_root_filesystem; then
314 MOUNT_DEV="${CRYPT_DEV}"
315 else
316 msg "ERROR: Encryption failed - booting without encryption"
317 MOUNT_DEV="${ROOT_DEV}"
318 fi
319 fi
320 else
321 msg "TPM not available - skipping encryption"
322 MOUNT_DEV="${ROOT_DEV}"
323 fi
324 fi
325
326 # Unmount boot partition before switching root
327 umount "${BOOT_MNT}"
328
329 # Mount root filesystem to $ROOTFS_DIR (framework expects this)
330 msg "Mounting root filesystem..."
331 mkdir -p ${ROOTFS_DIR}
332 mount "${MOUNT_DEV}" ${ROOTFS_DIR} || {
333 fatal "ERROR: Failed to mount root filesystem!"
334 }
335
336 # Clean up tmpfs and sensitive variables
337 rm -f "${TPM_PRIMARY_CTX}" "${TPM_KEY_PUB}" "${TPM_KEY_PRIV}" "${TPM_KEY_CTX}"
338 unset LUKS_KEY TPM_AVAILABLE MOUNT_DEV TEE_SUPPLICANT_PID
339
340 msg "Boot complete"
341}
diff --git a/meta-ti-bsp/dynamic-layers/tpm-layer/recipes-ti/initramfs/initramfs-module-luks-ftpm_1.0.bb b/meta-ti-bsp/dynamic-layers/tpm-layer/recipes-ti/initramfs/initramfs-module-luks-ftpm_1.0.bb
new file mode 100644
index 00000000..b2a41d08
--- /dev/null
+++ b/meta-ti-bsp/dynamic-layers/tpm-layer/recipes-ti/initramfs/initramfs-module-luks-ftpm_1.0.bb
@@ -0,0 +1,43 @@
1SUMMARY = "initramfs support for LUKS encryption with fTPM"
2DESCRIPTION = "Provides LUKS2 full disk encryption using firmware TPM (fTPM) for key management on TI K3 platforms"
3
4LICENSE = "MIT"
5LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420"
6
7# Only build for platforms with optee-ftpm support
8COMPATIBLE_MACHINE = "null"
9COMPATIBLE_MACHINE:k3 = "${@bb.utils.contains('MACHINE_FEATURES', 'optee-ftpm', '.*', 'null', d)}"
10
11FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
12
13SRC_URI = "file://luksftpm"
14
15S = "${UNPACKDIR}"
16
17do_install() {
18 install -d ${D}/init.d
19 # Install as 85-luksftpm (runs after udev at 01, before rootfs at 90)
20 install -m 0755 ${UNPACKDIR}/luksftpm ${D}/init.d/85-luksftpm
21}
22
23FILES:${PN} = "/init.d/85-luksftpm"
24
25# Runtime dependencies
26RDEPENDS:${PN} = "\
27 initramfs-framework-base \
28 busybox \
29 kmod \
30 cryptsetup \
31 tpm2-tools \
32 tpm2-tss \
33 libtss2-tcti-device \
34 optee-client \
35 optee-ftpm \
36 e2fsprogs-e2fsck \
37 e2fsprogs-resize2fs \
38 e2fsprogs-tune2fs \
39 util-linux-blkid \
40 kernel-module-tpm-ftpm-tee \
41"
42
43PACKAGE_ARCH = "${MACHINE_ARCH}"
diff --git a/meta-ti-bsp/dynamic-layers/tpm-layer/recipes-ti/initramfs/packagegroup-ti-core-initramfs.bbappend b/meta-ti-bsp/dynamic-layers/tpm-layer/recipes-ti/initramfs/packagegroup-ti-core-initramfs.bbappend
new file mode 100644
index 00000000..52c82389
--- /dev/null
+++ b/meta-ti-bsp/dynamic-layers/tpm-layer/recipes-ti/initramfs/packagegroup-ti-core-initramfs.bbappend
@@ -0,0 +1,3 @@
1LUKS_ENCRYPTION ?= "${@bb.utils.contains('MACHINE_FEATURES', 'optee-ftpm', 'initramfs-module-luks-ftpm', '', d)}"
2
3RDEPENDS:${PN}:append = " ${@bb.utils.contains('DISTRO_FEATURES', 'luks', '${LUKS_ENCRYPTION}', '', d)}"
diff --git a/meta-ti-bsp/dynamic-layers/tpm-layer/recipes-ti/initramfs/ti-core-initramfs.bbappend b/meta-ti-bsp/dynamic-layers/tpm-layer/recipes-ti/initramfs/ti-core-initramfs.bbappend
new file mode 100644
index 00000000..8901d0bf
--- /dev/null
+++ b/meta-ti-bsp/dynamic-layers/tpm-layer/recipes-ti/initramfs/ti-core-initramfs.bbappend
@@ -0,0 +1 @@
INITRAMFS_MAXSIZE = "200000"