sycamore_row_5G: sync validated TWRP bring-up
This commit is contained in:
parent
11a5d1b7a6
commit
3745f771d4
244 changed files with 240 additions and 4201 deletions
43
Android.bp
43
Android.bp
|
|
@ -10,46 +10,3 @@ cc_prebuilt_library_shared {
|
|||
none: true,
|
||||
},
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "sycamore_fscryptd",
|
||||
defaults: [
|
||||
"vold_default_flags",
|
||||
"vold_default_libs",
|
||||
],
|
||||
srcs: ["fscryptd/sycamore_fscryptd.cpp"],
|
||||
include_dirs: ["vendor/twrp/libfscrypt/include"],
|
||||
static_libs: ["libvold_fscrypt_helper"],
|
||||
header_libs: ["libvold_headers"],
|
||||
shared_libs: [
|
||||
"android.hardware.confirmationui@1.0",
|
||||
"android.hardware.gatekeeper@1.0",
|
||||
"android.hardware.health.storage@1.0",
|
||||
"android.hardware.health.storage-V1-ndk_platform",
|
||||
"android.hardware.keymaster@4.1",
|
||||
"android.hardware.security.keymint-V1-ndk_platform",
|
||||
"android.hardware.weaver@1.0",
|
||||
"android.security.apc-ndk_platform",
|
||||
"android.system.keystore2-V1-ndk_platform",
|
||||
"android.security.authorization-ndk_platform",
|
||||
"android.security.maintenance-ndk_platform",
|
||||
"libbase",
|
||||
"libbinder",
|
||||
"libbinder_ndk",
|
||||
"libgatekeeper",
|
||||
"libgatekeeper_aidl",
|
||||
"libhardware",
|
||||
"libhidlbase",
|
||||
"libkeymaster4_1support",
|
||||
"libkeystoreinfo",
|
||||
"libkeystore-attestation-application-id",
|
||||
"libkeymint_support",
|
||||
"liblog",
|
||||
"libchrome",
|
||||
],
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
"-Wextra",
|
||||
],
|
||||
}
|
||||
|
|
|
|||
11
Android.mk
11
Android.mk
|
|
@ -54,15 +54,4 @@ $(eval $(call sycamore-recovery-library,sycamore_soft_attestation,libsoft_attest
|
|||
$(eval $(call sycamore-recovery-library,sycamore_cppbor_external,libcppbor_external.so,vendor/lib64))
|
||||
$(eval $(call sycamore-recovery-library,sycamore_cppcose_rkp,libcppcose_rkp.so,vendor/lib64))
|
||||
|
||||
# Diagnostic V8 only: observe the 64-byte STORAGE_KEY at Beanpod's final
|
||||
# userspace boundary, then tail-call the byte-identical stock A16 function.
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := libsycamore_keytrace
|
||||
LOCAL_SRC_FILES := diagnostics/keytrace.cpp
|
||||
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
|
||||
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/vendor/lib64
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_SHARED_LIBRARIES := libcrypto libdl liblog
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -102,13 +102,24 @@ endif
|
|||
# PLATFORM already provides the complete stock module tree. Remove the duplicate
|
||||
# device recovery metadata after recovery-root population and before mkbootfs;
|
||||
# otherwise its recovery-oriented modules.load shadows the stock normal list.
|
||||
# Final recovery-root preparation:
|
||||
# - remove duplicate recovery module metadata so the pristine PLATFORM ramdisk wins
|
||||
# - present the exact production XT2575-4 vendor identity before Microtrust starts
|
||||
BOARD_RECOVERY_IMAGE_PREPARE = test -n "$(TARGET_RECOVERY_ROOT_OUT)" && \
|
||||
rm -rf -- "$(TARGET_RECOVERY_ROOT_OUT)/lib/modules"
|
||||
TARGET_RECOVERY_PIXEL_FORMAT := "BGRA_8888"
|
||||
RECOVERY_GRAPHICS_FORCE_USE_LINELENGTH := true
|
||||
rm -rf -- "$(TARGET_RECOVERY_ROOT_OUT)/lib/modules" && \
|
||||
sed -i \
|
||||
-e 's/^ro.product.vendor.device=sycamore_row_5G$$/ro.product.vendor.device=XT2575-4/' \
|
||||
-e 's/^ro.product.vendor.name=twrp_sycamore_row_5G$$/ro.product.vendor.name=XT2575-4/' \
|
||||
"$(TARGET_RECOVERY_ROOT_OUT)/prop.default" && \
|
||||
grep -Fqx 'ro.product.device=XT2575-4' "$(TARGET_RECOVERY_ROOT_OUT)/prop.default" && \
|
||||
grep -Fqx 'ro.product.vendor.device=XT2575-4' "$(TARGET_RECOVERY_ROOT_OUT)/prop.default" && \
|
||||
grep -Fqx 'ro.product.vendor.name=XT2575-4' "$(TARGET_RECOVERY_ROOT_OUT)/prop.default" && \
|
||||
grep -Fqx 'ro.product.vendor.model=XT2575-4' "$(TARGET_RECOVERY_ROOT_OUT)/prop.default" && \
|
||||
grep -Fqx 'ro.build.product=sycamore_row_5G' "$(TARGET_RECOVERY_ROOT_OUT)/prop.default"
|
||||
TARGET_RECOVERY_PIXEL_FORMAT := RGBX_8888
|
||||
BOARD_HAS_NO_SELECT_BUTTON := true
|
||||
|
||||
# V18: exact production teei_daemon domain and narrowly scoped Microtrust
|
||||
# Exact production teei_daemon domain and narrowly scoped Microtrust
|
||||
# device labels. The platform policy already defines tee/tee_exec and its
|
||||
# init transition; this directory supplies only Sycamore-specific paths/types.
|
||||
BOARD_VENDOR_SEPOLICY_DIRS += $(DEVICE_PATH)/sepolicy/vendor
|
||||
|
|
@ -126,39 +137,18 @@ TW_INCLUDE_FASTBOOTD := true
|
|||
# Preserve the device recovery.fstab mount options. The stock additional fstab
|
||||
# otherwise reparses /metadata and drops its recovery-only context= option.
|
||||
TW_SKIP_ADDITIONAL_FSTAB := true
|
||||
# Build the crypto-only helper against the existing platform libvold, then use
|
||||
# TeamWin's supported device hook to relink it into recovery /system/bin.
|
||||
TW_RECOVERY_ADDITIONAL_RELINK_BINARY_FILES += $(TARGET_OUT_EXECUTABLES)/sycamore_fscryptd
|
||||
# The generic TWRP 12.1 synthetic /super object exposes raw restore/image
|
||||
# writes while logical mappings are live. Keep super discovery, but hide those
|
||||
# unsafe UI operations on this virtual A/B device.
|
||||
TW_EXCLUDE_SUPER_BACKUP_FLASH := true
|
||||
TW_INTERNAL_STORAGE_PATH := "/data/media/0"
|
||||
TW_INTERNAL_STORAGE_MOUNT_POINT := "data"
|
||||
TW_USB_STORAGE := false
|
||||
# Runtime diagnostic: the initial configfs ADB gadget works, but entering the
|
||||
# GUI makes TWRP request mtp,adb. This tree has no configfs mtp,adb property
|
||||
# action, so that transition unbinds the UDC and loses all host enumeration.
|
||||
# Keep the proven adb-only gadget until MTK configfs MTP is implemented.
|
||||
|
||||
# Tree-only FBE diagnostic: avoid twrpApex::loadApexImage(), whose TWRP 12.1
|
||||
# implementation seeks an already-closed payload fd. Recovery's own crypto
|
||||
# binaries and libraries are packaged in the ramdisk, so first prove the stock
|
||||
# KeyMint/TEE chain without depending on Android's runtime APEX mounts. The
|
||||
# generic source correction is retained separately as patch 0002.
|
||||
# TWRP 12.1's APEX loader is incompatible with this recovery's crypto path.
|
||||
# Sycamore packages the required Android 16 crypto binaries and libraries
|
||||
# directly in the recovery ramdisk, so recovery APEX mounting is unnecessary.
|
||||
TW_EXCLUDE_APEX := true
|
||||
|
||||
# Stock FBE v2 + metadata encryption. Branch must provide Android 15/16 crypto.
|
||||
# Temporary first-hardware-boot diagnostic: keep /data encrypted and unmounted,
|
||||
# and bypass the synchronous Android 16 metadata/FBE decrypt path so the GUI
|
||||
# can start. Re-enable these only after the KeyMint/Keystore2 dependency chain
|
||||
# is made compatible with the stock Android 16 vendor environment.
|
||||
SYCAMORE_DIAGNOSTIC_NO_DECRYPT := false
|
||||
ifneq ($(SYCAMORE_DIAGNOSTIC_NO_DECRYPT),true)
|
||||
# Stock FBE v2 with metadata encryption.
|
||||
TW_INCLUDE_CRYPTO := true
|
||||
TW_INCLUDE_CRYPTO_FBE := true
|
||||
TW_INCLUDE_FBE_METADATA_DECRYPT := true
|
||||
endif
|
||||
BOARD_USES_METADATA_PARTITION := true
|
||||
|
||||
# Bring-up/debug essentials; no missing-dependency escape hatch.
|
||||
|
|
@ -171,7 +161,6 @@ TW_EXCLUDE_DEFAULT_USB_INIT := true
|
|||
TW_DEFAULT_LANGUAGE := en
|
||||
TW_EXTRA_LANGUAGES := true
|
||||
TW_USE_SERIALNO_PROPERTY_FOR_DEVICE_ID := true
|
||||
|
||||
# Preserve the exact factory vendor_boot AVB fingerprint independently of the
|
||||
# recovery build fingerprint.
|
||||
BOARD_AVB_VENDOR_BOOT_FINGERPRINT := Motorola/XT2575-4/XT2575-4:15/AP3A.240905.015.A2/9bdeac_017:user/release-keys
|
||||
|
|
@ -185,8 +174,8 @@ BOARD_AVB_VENDOR_BOOT_ADD_HASH_FOOTER_ARGS += \
|
|||
# Removable storage filesystem support.
|
||||
TW_INCLUDE_NTFS_3G := true
|
||||
|
||||
# R7v9.60: platform-side TWRP FBE property definition
|
||||
# Platform-side TWRP FBE property definition.
|
||||
SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS += device/motorola/sycamore_row_5G/sepolicy/public
|
||||
|
||||
# R7v9.60: platform-side TWRP FBE property context
|
||||
# Platform-side TWRP FBE property context.
|
||||
SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS += device/motorola/sycamore_row_5G/sepolicy/private
|
||||
|
|
|
|||
|
|
@ -1,162 +0,0 @@
|
|||
DEVICE_PATH := device/motorola/sycamore_row_5G
|
||||
|
||||
# Architecture (64-bit recovery; runtime CPU properties identify Cortex-A55/A76 cores).
|
||||
TARGET_ARCH := arm64
|
||||
TARGET_ARCH_VARIANT := armv8-a
|
||||
TARGET_CPU_ABI := arm64-v8a
|
||||
TARGET_CPU_ABI2 :=
|
||||
TARGET_CPU_VARIANT := generic
|
||||
TARGET_CPU_VARIANT_RUNTIME := cortex-a55
|
||||
TARGET_USES_64_BIT_BINDER := true
|
||||
|
||||
# Platform and assertions.
|
||||
TARGET_BOARD_PLATFORM := mt6835
|
||||
TARGET_BOOTLOADER_BOARD_NAME := sycamore_row_5G
|
||||
TARGET_NO_BOOTLOADER := true
|
||||
TARGET_OTA_ASSERT_DEVICE := sycamore_row_5G,XT2575-4
|
||||
# Stock first API level is 35, but twrp-12.1 is an API 32 build and rejects a
|
||||
# BOARD_SHIPPING_API_LEVEL newer than its platform SDK. Keep the measured value
|
||||
# in the bring-up log rather than emitting a false API-32 build property.
|
||||
|
||||
# The stock Beanpod KeyMint service configures its TA from these properties.
|
||||
# Pristine A16 vendor_boot supplies 2026-07-05 for both, and the live metadata
|
||||
# key blob is bound to OS patch level 202607. Leaving the TWRP 12.1 defaults
|
||||
# (202204 / empty) makes secure world reject that newer blob as a downgrade.
|
||||
# These are exact stock inputs, not the old twrpdtgen 2099 bypass.
|
||||
PLATFORM_SECURITY_PATCH := 2026-07-05
|
||||
VENDOR_SECURITY_PATCH := 2026-07-05
|
||||
|
||||
# Exact factory kernel, DTB, and vendor_boot v4 header addresses. These values
|
||||
# are mechanically extracted from the pristine ZUI 17.5 vendor_boot image.
|
||||
TARGET_PREBUILT_KERNEL := $(DEVICE_PATH)/prebuilt/kernel
|
||||
BOARD_INCLUDE_DTB_IN_BOOTIMG := true
|
||||
BOARD_PREBUILT_DTBIMAGE_DIR := $(DEVICE_PATH)/prebuilt/dtb
|
||||
BOARD_BOOT_HEADER_VERSION := 4
|
||||
BOARD_KERNEL_PAGESIZE := 4096
|
||||
BOARD_KERNEL_BASE := 0x40000000
|
||||
BOARD_RAMDISK_USE_LZ4 := true
|
||||
BOARD_KERNEL_SEPARATED_DTBO := true
|
||||
BOARD_MKBOOTIMG_ARGS += --header_version $(BOARD_BOOT_HEADER_VERSION)
|
||||
BOARD_MKBOOTIMG_ARGS += --kernel_offset 0x00000000
|
||||
BOARD_MKBOOTIMG_ARGS += --ramdisk_offset 0x26f00000
|
||||
BOARD_MKBOOTIMG_ARGS += --tags_offset 0x07c80000
|
||||
BOARD_MKBOOTIMG_ARGS += --dtb_offset 0x07c80000
|
||||
BOARD_MKBOOTIMG_ARGS += --vendor_cmdline "bootopt=64S3,32N2,64N2"
|
||||
|
||||
# Preserve the pristine stock vendor ramdisk byte-for-byte as the unnamed base
|
||||
# PLATFORM ramdisk. AOSP then appends the generated TWRP RECOVERY fragment.
|
||||
# This matches the factory vendor_boot v4 layout and preserves overlay ordering.
|
||||
BOARD_PREBUILT_VENDOR_RAMDISK := \
|
||||
$(DEVICE_PATH)/prebuilt/vendor_ramdisk/platform.cpio.lz4
|
||||
|
||||
# Physical partition sizes measured from GPT/factory images.
|
||||
BOARD_BOOTIMAGE_PARTITION_SIZE := 67108864
|
||||
BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE := 67108864
|
||||
BOARD_INIT_BOOT_IMAGE_PARTITION_SIZE := 8388608
|
||||
BOARD_DTBOIMG_PARTITION_SIZE := 8388608
|
||||
BOARD_PREBUILT_DTBOIMAGE := $(DEVICE_PATH)/prebuilt/dtbo.img
|
||||
|
||||
# Live liblp metadata: v10.2, 64 KiB max metadata, three slots, virtual A/B.
|
||||
BOARD_SUPER_PARTITION_SIZE := 11811160064
|
||||
BOARD_SUPER_PARTITION_GROUPS := main_dynamic_partitions
|
||||
BOARD_MAIN_DYNAMIC_PARTITIONS_SIZE := 11809062912
|
||||
# API-32 build/make cannot generate system_dlkm. It remains in recovery.fstab
|
||||
# and live liblp metadata; this recovery-only target does not build super.
|
||||
BOARD_MAIN_DYNAMIC_PARTITIONS_PARTITION_LIST := \
|
||||
odm_dlkm product system system_ext vendor vendor_dlkm
|
||||
|
||||
TARGET_COPY_OUT_SYSTEM_EXT := system_ext
|
||||
TARGET_COPY_OUT_PRODUCT := product
|
||||
TARGET_COPY_OUT_VENDOR := vendor
|
||||
TARGET_COPY_OUT_VENDOR_DLKM := vendor_dlkm
|
||||
TARGET_COPY_OUT_ODM_DLKM := odm_dlkm
|
||||
|
||||
BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE := erofs
|
||||
BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE := erofs
|
||||
BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE := erofs
|
||||
BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := erofs
|
||||
BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_TYPE := erofs
|
||||
BOARD_ODM_DLKMIMAGE_FILE_SYSTEM_TYPE := erofs
|
||||
BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE := f2fs
|
||||
TARGET_USERIMAGES_USE_EXT4 := true
|
||||
TARGET_USERIMAGES_USE_F2FS := true
|
||||
|
||||
# Recovery lives in vendor_boot. AOSP build/make emits a v4 RECOVERY ramdisk
|
||||
# fragment when both switches below are true; stock's platform fragment already
|
||||
# proves that all recovery resources belong in vendor_boot on this device.
|
||||
TARGET_NO_RECOVERY := true
|
||||
TW_HAS_NO_RECOVERY_PARTITION := true
|
||||
BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE := true
|
||||
BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT := true
|
||||
BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOT := true
|
||||
TARGET_RECOVERY_FSTAB := $(DEVICE_PATH)/recovery.fstab
|
||||
TARGET_RECOVERY_PIXEL_FORMAT := RGBX_8888
|
||||
BOARD_HAS_NO_SELECT_BUTTON := true
|
||||
|
||||
# V18: exact production teei_daemon domain and narrowly scoped Microtrust
|
||||
# device labels. The platform policy already defines tee/tee_exec and its
|
||||
# init transition; this directory supplies only Sycamore-specific paths/types.
|
||||
BOARD_VENDOR_SEPOLICY_DIRS += $(DEVICE_PATH)/sepolicy/vendor
|
||||
|
||||
# Display values measured from Android.
|
||||
TARGET_SCREEN_WIDTH := 1600
|
||||
TARGET_SCREEN_HEIGHT := 2560
|
||||
TARGET_SCREEN_DENSITY := 320
|
||||
TW_THEME := portrait_hdpi
|
||||
TW_FRAMERATE := 90
|
||||
|
||||
# A/B, dynamic partitions, fastbootd and storage.
|
||||
AB_OTA_UPDATER := true
|
||||
TW_INCLUDE_FASTBOOTD := true
|
||||
TW_INTERNAL_STORAGE_PATH := "/data/media/0"
|
||||
TW_INTERNAL_STORAGE_MOUNT_POINT := "data"
|
||||
TW_BACKUP_DATA_MEDIA := true
|
||||
TW_USB_STORAGE := false
|
||||
# Runtime diagnostic: the initial configfs ADB gadget works, but entering the
|
||||
# GUI makes TWRP request mtp,adb. This tree has no configfs mtp,adb property
|
||||
# action, so that transition unbinds the UDC and loses all host enumeration.
|
||||
# Keep the proven adb-only gadget until MTK configfs MTP is implemented.
|
||||
TW_EXCLUDE_MTP := true
|
||||
|
||||
# Tree-only FBE diagnostic: avoid twrpApex::loadApexImage(), whose TWRP 12.1
|
||||
# implementation seeks an already-closed payload fd. Recovery's own crypto
|
||||
# binaries and libraries are packaged in the ramdisk, so first prove the stock
|
||||
# KeyMint/TEE chain without depending on Android's runtime APEX mounts. The
|
||||
# generic source correction is retained separately as patch 0002.
|
||||
TW_EXCLUDE_APEX := true
|
||||
|
||||
# Stock FBE v2 + metadata encryption. Branch must provide Android 15/16 crypto.
|
||||
# Temporary first-hardware-boot diagnostic: keep /data encrypted and unmounted,
|
||||
# and bypass the synchronous Android 16 metadata/FBE decrypt path so the GUI
|
||||
# can start. Re-enable these only after the KeyMint/Keystore2 dependency chain
|
||||
# is made compatible with the stock Android 16 vendor environment.
|
||||
SYCAMORE_DIAGNOSTIC_NO_DECRYPT := false
|
||||
ifneq ($(SYCAMORE_DIAGNOSTIC_NO_DECRYPT),true)
|
||||
TW_INCLUDE_CRYPTO := true
|
||||
TW_INCLUDE_CRYPTO_FBE := true
|
||||
TW_INCLUDE_FBE_METADATA_DECRYPT := true
|
||||
endif
|
||||
BOARD_USES_METADATA_PARTITION := true
|
||||
|
||||
# Bring-up/debug essentials; no missing-dependency escape hatch.
|
||||
TARGET_USES_LOGD := true
|
||||
TWRP_INCLUDE_LOGCAT := true
|
||||
TW_INCLUDE_REPACKTOOLS := true
|
||||
TW_INCLUDE_RESETPROP := true
|
||||
TW_INCLUDE_LIBRESETPROP := true
|
||||
TW_EXCLUDE_DEFAULT_USB_INIT := true
|
||||
TW_DEFAULT_LANGUAGE := en
|
||||
TW_EXTRA_LANGUAGES := true
|
||||
|
||||
# Preserve the exact factory vendor_boot AVB fingerprint independently of the
|
||||
# recovery build fingerprint.
|
||||
BOARD_AVB_VENDOR_BOOT_FINGERPRINT := Motorola/XT2575-4/XT2575-4:15/AP3A.240905.015.A2/9bdeac_017:user/release-keys
|
||||
|
||||
# Match the stock algorithm-NONE vendor_boot hash-footer design. The salt is
|
||||
# extracted from the pristine footer; no signing key is used or invented.
|
||||
BOARD_AVB_ENABLE := true
|
||||
BOARD_AVB_VENDOR_BOOT_ADD_HASH_FOOTER_ARGS += \
|
||||
--salt 11503e95ee971adc6c444e3ae47f564f178032ee9bbcf99d2ccfdc0895c67ed7
|
||||
|
||||
# Removable storage filesystem support.
|
||||
TW_INCLUDE_NTFS_3G := true
|
||||
|
|
@ -1,228 +0,0 @@
|
|||
# Sycamore Android 16 FBE cmd 0x18 investigation
|
||||
|
||||
Date: 2026-08-27
|
||||
|
||||
Baseline: hardware-tested V14 wrapped-first vendor_boot, SHA-256
|
||||
`d657365e5c14ba0bc1e93e9fc0ec38acb18f935e222d1bae66377011b96b9d15`.
|
||||
|
||||
Evidence labels in this report are **PROVEN**, **EXPECTED**, **UNKNOWN**, and
|
||||
**EXCLUDED**.
|
||||
|
||||
## A. Recovery state immediately before the first cmd 0x18
|
||||
|
||||
The first V14 conversion is at `v14-native-runtime-failure/logcat-all.txt:2942-2957`,
|
||||
at 19:01:29.957-19:01:29.959. Before that point recovery had already proven:
|
||||
|
||||
- `vendor.soter.teei.init=INIT_OK`
|
||||
- `vendor.soter.teei.km.init=config_patch_level_sucess`
|
||||
- `vendor.soter.teei.km.version=v2.0.0`
|
||||
- `vendor.soter.teei.persist=OPEN`
|
||||
- `vendor.soter.teei.rpmb.flag=ok`
|
||||
- persist selector 3
|
||||
- successful c09 TA load, secure-storage manager startup, physical RPMB commands,
|
||||
`rpmb key is programmed`, KeyMint configuration, SharedSecret, metadata unwrap,
|
||||
systemwide outer unwrap, and one stock-shaped Begin/Update/Finish sequence.
|
||||
|
||||
The retained recovery property dump does not contain:
|
||||
|
||||
- `vendor.soter.teei.googlekey.status`
|
||||
- `vendor.soter.teei.logini`
|
||||
|
||||
Recovery later logs `logini thread failed` at 19:02:05.108, about 35 seconds after
|
||||
the first failure. This proves a final recovery-state difference, but does not prove
|
||||
that logini participates in cmd 0x18.
|
||||
|
||||
## B. Healthy-stock Soter comparison
|
||||
|
||||
The archived stock snapshot contains:
|
||||
|
||||
| Property | Stock snapshot | V14 retained state before/around failure |
|
||||
|---|---|---|
|
||||
| `vendor.soter.teei.googlekey.status` | `ok` | absent |
|
||||
| `vendor.soter.teei.init` | `INIT_OK` | `INIT_OK` |
|
||||
| `vendor.soter.teei.km.init` | `config_patch_level_sucess` | same |
|
||||
| `vendor.soter.teei.km.version` | `v2.0.0` | `v2.0.0` |
|
||||
| `vendor.soter.teei.logini` | `start` | absent; later logini thread failure |
|
||||
| `vendor.soter.teei.persist` | `OPEN` | `OPEN` |
|
||||
| `vendor.soter.teei.rpmb.flag` | `ok` | `ok` |
|
||||
|
||||
Stock `microtrust.rc:245-246` sets `vendor.soter.teei.logini=start` on the Android
|
||||
`post-fs-data` trigger. It is an init-set request to `teei_daemon`, not proof by
|
||||
itself that a secure-world transition completed. The stock property snapshot was
|
||||
captured after DE storage was available, so it cannot prove that logini preceded
|
||||
stock's first storage-key conversion. Android init describes `post-fs-data` as the
|
||||
stage at which `/data` has already been mounted; therefore forcing logini before
|
||||
conversion would not reproduce a proven stock ordering.
|
||||
|
||||
No local rc file was found that directly sets `googlekey.status`. The value is
|
||||
therefore **EXPECTED** to be service/secure-world-derived, but its exact setter and
|
||||
pre-conversion timing remain **UNKNOWN**.
|
||||
|
||||
Conclusion: `persist=OPEN` and `rpmb.flag=ok` are matched and correspond to observed
|
||||
real VFS/RPMB activity. `logini` and `googlekey.status` differ in final visibility,
|
||||
but neither is yet connected to cmd 0x18 timing.
|
||||
|
||||
## C. Exact 64-byte storage-key provenance
|
||||
|
||||
The source directory is `/data/unencrypted/key`:
|
||||
|
||||
1. `keymaster_key_blob` is a 444-byte ordinary KeyMint AES wrapping-key blob,
|
||||
SHA-256
|
||||
`24449b28dedeecc82b0abfb571ef6aa93151608e841fbbf9dd9bdb907ff89c87`.
|
||||
2. `secdiscardable` contributes to the application ID computed by
|
||||
`KeyStorage.cpp::generateAppId()`.
|
||||
3. `encrypted_key` is a 92-byte AES-GCM container: 12-byte nonce, 64-byte
|
||||
ciphertext/plaintext length, and 16-byte tag. Its SHA-256 is
|
||||
`7700695d0e5c1605d9d1c56669cb4130588c1054766ac735488fa76f4fd47312`.
|
||||
4. `retrieveKey()` reads the files at `system/vold/KeyStorage.cpp:630-652`.
|
||||
5. `decryptWithKeymasterKey()` authenticates and decrypts the 92-byte container.
|
||||
6. The resulting 64-byte plaintext is the proprietary `TAG_STORAGE_KEY` blob.
|
||||
7. `exportWrappedStorageKey()` at `system/vold/KeyStorage.cpp:189-197` copies it
|
||||
without transformation into `Keymaster::exportKey()`.
|
||||
8. `Keymaster::exportKey()` at `system/vold/Keymaster.cpp:167-191` places the same
|
||||
bytes in a `Domain::BLOB` descriptor.
|
||||
9. Keystore2 at `system/security/keystore2/src/security_level.rs:892-962` passes
|
||||
the byte vector unchanged to `IKeyMintDevice::convertStorageKeyToEphemeral()`.
|
||||
10. Beanpod serializes the legacy export request as 12-byte empty AuthorizationSet,
|
||||
4-byte RAW KeyFormat, 4-byte blob length, and the 64-byte blob: 84 bytes total.
|
||||
|
||||
V14 hash-only checkpoints A, B, C, and D all report 64 bytes with SHA-256
|
||||
`3c36a06c93c07adeda069dd413b2df8f2e9b54371f3920e5de40ea6f318e8f83`.
|
||||
The complete 84-byte request SHA-256 is
|
||||
`7c4f5fdd21de15b396f5b739cbb41f32a3944046902c786ceed9a2b829e56647`.
|
||||
|
||||
No raw key, nonce, HMAC, or credential bytes are recorded. This is intentional:
|
||||
lengths and hashes prove transport identity without exposing live key material.
|
||||
|
||||
The 64-byte length is **PROVEN expected for this exact existing Sycamore blob**:
|
||||
stock decrypts the same key lineage, the authenticated outer container has a
|
||||
64-byte plaintext, and the TA reports `DeserializeAuthEncryptedBlob ... (64)`.
|
||||
|
||||
## D. Recovery code path and cmd 0x18 construction
|
||||
|
||||
`fscrypt_initialize_systemwide_keys()` at `system/vold/FsCrypt.cpp:452-495`
|
||||
retrieves `/data/unencrypted/key`, then `install_storage_key()` at lines 268-279
|
||||
calls `exportWrappedStorageKey()` when hardware-wrapped mode is selected.
|
||||
|
||||
The request contains:
|
||||
|
||||
- empty client/application AuthorizationSets;
|
||||
- `KeyFormat::RAW`;
|
||||
- the unmodified 64-byte opaque blob;
|
||||
- no credential, SID, auth token, application ID, or application data.
|
||||
|
||||
Beanpod command `0x18` is its legacy Keymaster export-key command encoding. It is
|
||||
not a distinct 0x18-only userspace serializer invented by TWRP.
|
||||
|
||||
## E. Android 16 comparison
|
||||
|
||||
Android 16 AOSP `system/vold` retains the same architecture:
|
||||
|
||||
- vold passes the opaque storage key as `Domain::BLOB` to Keystore2;
|
||||
- Keystore2 calls `convertStorageKeyToEphemeral()` directly;
|
||||
- only `KEY_REQUIRES_UPGRADE` invokes `upgradeKey()` and retries;
|
||||
- vold intentionally continues storing its original storage blob because its outer
|
||||
wrapper already handles version binding.
|
||||
|
||||
V14 follows this behavior. Beanpod returns `INVALID_KEY_BLOB`, not
|
||||
`KEY_REQUIRES_UPGRADE`, so the absent upgrade retry is correct.
|
||||
|
||||
Material source drift found in the old tree is creation-side, not conversion-side:
|
||||
|
||||
- the local `generateWrappedStorageKey()` requests rollback resistance through its
|
||||
generic generator and adds private `KM_TAG_FBE_ICE`;
|
||||
- newer AOSP avoids rollback resistance for newly generated storage keys.
|
||||
|
||||
Neither changes the already-existing 64-byte stock blob or its conversion request.
|
||||
The exact stock A16 vold binary contains `wrappedkey_v0`,
|
||||
`fscrypt_initialize_systemwide_keys`, and the same ephemeral-key path. A
|
||||
syntactically or semantically obsolete recovery request is therefore **EXCLUDED at
|
||||
the presently visible boundary**.
|
||||
|
||||
## F. Public recovery references
|
||||
|
||||
- Agate: credible working TWRP + Microtrust/Beanpod + FBE/metadata reference, but
|
||||
userdata lacks `wrappedkey_v0`; it does not exercise cmd 0x18.
|
||||
- Pissarro: useful Beanpod/TEEI startup ordering, but no proven hardware-wrapped
|
||||
storage-key decryption.
|
||||
- Air: closest MT6835 architecture reference, but crypto flags are disabled and the
|
||||
tree is explicitly WIP.
|
||||
- Dew: modern AIDL KeyMint/Keystore2 architecture, but WIP and no verified
|
||||
hardware-wrapped-key decryption result.
|
||||
- TB351FU: valuable modern Lenovo Soter property control; its published recovery
|
||||
reports encrypted internal storage inaccessible and its stock fstab does not
|
||||
establish hardware-wrapped-key use.
|
||||
|
||||
No verified public “unicorn” was found that simultaneously demonstrates MediaTek,
|
||||
Microtrust/TEEI, Beanpod, `wrappedkey_v0`, and successful recovery decryption.
|
||||
|
||||
## G. Microtrust hidden state
|
||||
|
||||
The MT6895 public driver names `boot_decryto_lock`, `boot_soter_flag`,
|
||||
`keymaster_call_flag`, `soter_error_flag`, and `teei_capi_ready`, and enforces
|
||||
`teei_daemon` identity for VFS calls. These establish that hidden kernel/secure-world
|
||||
state exists. Sycamore runtime proves VFS, TA load, RPMB, and ordinary KeyMint calls
|
||||
advance far enough to work.
|
||||
|
||||
No local Sycamore kernel source exposes equivalent variables, and no retained trace
|
||||
connects any one of them to cmd 0x18. They remain architectural context, not a
|
||||
root-cause result.
|
||||
|
||||
The exact Sycamore TA is a 930,857-byte signed/encrypted Microtrust container, not
|
||||
an ELF image, so normal `readelf`/`objdump` analysis cannot isolate its dispatcher.
|
||||
Runtime secure-world diagnostics nevertheless identify the decisive path:
|
||||
|
||||
`ParseKeyBlob()` -> `DeserializeAuthEncryptedBlob()` -> `AES_decrypt_ctr()` ->
|
||||
integrity/hash comparison failure -> `-33`.
|
||||
|
||||
This is after the 64-byte blob has reached authenticated blob decoding. It strongly
|
||||
favors a structurally recognized blob whose authentication/derivation context does
|
||||
not reproduce stock over a malformed 84-byte request.
|
||||
|
||||
## H. Ranked remaining causes
|
||||
|
||||
1. **Medium-high:** secure-world storage-key authentication/KDF context differs
|
||||
between normal boot and recovery. This best matches the TA's integrity comparison
|
||||
failure while ordinary blobs and the same session work.
|
||||
2. **Medium:** a storage-specific secure-world initialization transition occurs in
|
||||
stock but not recovery before conversion. `googlekey.status`/logini are observable
|
||||
leads, but their timing and causal relationship are unproven.
|
||||
3. **Medium-low:** the retained 64-byte blob depends on secure-storage lineage/state
|
||||
not exercised by ordinary metadata keys. RPMB transport works, but that does not
|
||||
prove every SST namespace/derived key is identical.
|
||||
4. **Low:** userspace serialization or Android-version drift. A16 and recovery paths
|
||||
match, and A/B/C/D plus the complete request hash exclude mutation.
|
||||
5. **Low:** malformed length/version presented by vold. The outer container
|
||||
authenticates, 64 bytes is the actual stored object, and TA reaches integrity
|
||||
comparison rather than rejecting request structure.
|
||||
|
||||
Root-of-Trust/device-lock state remains a possible input to item 1, not a proven
|
||||
cause. Current-stock success under the same raw unlocked/orange boot properties
|
||||
prevents asserting a simple property-level ROT mismatch.
|
||||
|
||||
## I. Best next controlled experiment
|
||||
|
||||
The smallest justified next artifact is diagnostic-only: snapshot the seven Soter
|
||||
properties inside `Keymaster::exportKey()` immediately before the first
|
||||
`convertStorageKeyToEphemeral()` call. This proves exact boundary-time recovery
|
||||
state without setting properties, changing service order, exposing secrets, or
|
||||
altering the request.
|
||||
|
||||
Do **not** set `logini=start` yet. Stock sets it on `post-fs-data`, and available
|
||||
evidence does not prove that doing so before cmd 0x18 is stock-equivalent or safe.
|
||||
|
||||
The stock-side unresolved requirement is a trustworthy early-boot timing capture.
|
||||
The existing post-DE stock property dump cannot answer it, and invasive stock
|
||||
instrumentation could invalidate the control.
|
||||
|
||||
## J. Exact proposed change
|
||||
|
||||
One diagnostic addition in `system/vold/Keymaster.cpp`, immediately before
|
||||
`securityLevel->convertStorageKeyToEphemeral(...)`:
|
||||
|
||||
- read and log only the seven public `vendor.soter.teei.*` property strings;
|
||||
- keep the existing 64-byte length/SHA-256 checkpoint;
|
||||
- do not set any property or alter control flow.
|
||||
|
||||
No TA, Beanpod, Keystore2, KeyStorage, init, fstab, DTB, PLATFORM fragment, or key
|
||||
file would change functionally.
|
||||
89
README.md
89
README.md
|
|
@ -36,57 +36,48 @@ Vendor Boot Header | Version 4
|
|||
|
||||
Current state of features:
|
||||
|
||||
- [x] Correct screen/recovery size
|
||||
- [x] Working display
|
||||
- [x] Working touch
|
||||
- [x] Screen brightness control
|
||||
- [x] Power off
|
||||
- [x] Reboot to system
|
||||
- [x] Reboot to bootloader
|
||||
- [x] Reboot to recovery
|
||||
- [x] Fastboot / fastbootd
|
||||
- [x] ADB
|
||||
- [x] Internal storage detected
|
||||
- [x] External SD card detected
|
||||
- [x] exFAT external storage
|
||||
- [x] F2FS userdata support
|
||||
- [x] EXT4 support
|
||||
- [x] EROFS support
|
||||
- [x] Dynamic partition support
|
||||
- [x] A/B slot handling
|
||||
- [x] `vendor_boot` v4 support
|
||||
- [x] Stock PLATFORM vendor ramdisk preserved
|
||||
- [x] TWRP RECOVERY vendor ramdisk fragment
|
||||
- [x] Metadata encryption successfully decrypted
|
||||
- [x] `/data` block device successfully decrypted and mounted
|
||||
- [x] KeyMint service
|
||||
- [x] Gatekeeper service
|
||||
- [x] Keystore2 service
|
||||
- [ ] Full FBE decryption
|
||||
- [ ] User PIN/password decryption
|
||||
- [ ] Decrypted `/data/media`
|
||||
- [ ] MTP
|
||||
- [ ] Vibration / haptics
|
||||
- [ ] USB mass storage export
|
||||
- [ ] TWRP native `vendor_boot` installation from pristine stock image
|
||||
- [ ] All commonly modified partitions exposed for image flashing
|
||||
- Correct screen/recovery size
|
||||
- Working touch and display
|
||||
- ADB
|
||||
- Support EROFS/F2FS/EXT4/exFAT/NTFS
|
||||
- External SD card support
|
||||
- Dynamic partition support
|
||||
- A/B slot handling
|
||||
- `vendor_boot` v4 support
|
||||
- Stock PLATFORM vendor ramdisk preserved
|
||||
- TWRP RECOVERY vendor ramdisk fragment
|
||||
- Decrypt `/data` with user PIN/password
|
||||
- Decrypted `/data/media`
|
||||
- Metadata encryption
|
||||
- KeyMint service
|
||||
- Gatekeeper service
|
||||
- Keystore2 service
|
||||
- MediaTek/Microtrust TEE
|
||||
- MTP export
|
||||
- SELinux enforcing
|
||||
- Vibrate and set vibration
|
||||
|
||||
## Encryption status
|
||||
Still to validate before final release:
|
||||
|
||||
Metadata encryption is working and TWRP successfully creates and mounts the decrypted userdata block device.
|
||||
- Backup/restore to/from internal/external storage and ADB
|
||||
- ADB sideload
|
||||
- Poweroff and all reboot targets
|
||||
- Flashing zip/images from the TWRP UI
|
||||
- All important partitions listed in wipe/mount/backup lists
|
||||
- Input devices via USB-OTG
|
||||
- Correct date/time configuration
|
||||
- Battery level reporting
|
||||
- Brightness adjustment
|
||||
- Screenshot
|
||||
- Advanced recovery features
|
||||
|
||||
Current testing reaches the Android hardware-wrapped storage key path but fails during system-wide fscrypt key initialization.
|
||||
# Building
|
||||
|
||||
The current failure occurs in the MediaTek Beanpod KeyMint trusted application while processing storage-key conversion:
|
||||
```bash
|
||||
export ALLOW_MISSING_DEPENDENCIES=true
|
||||
source build/envsetup.sh
|
||||
lunch twrp_sycamore_row_5G-eng
|
||||
mka vendorbootimage -j$(nproc --all)
|
||||
```
|
||||
|
||||
```text
|
||||
cmd 0x18 / cmd 24
|
||||
km_error = -33
|
||||
|
||||
AES_decrypt_ctr:
|
||||
decrypt keyblob compare hash failed
|
||||
|
||||
DeserializeAuthEncryptedBlob:
|
||||
decrypt keyblob failed (-33)
|
||||
|
||||
**Copyright (C) 2023 A-Team Digital Solutions**
|
||||
**Copyright (C) 2026 BOBtheBlinker | A-Team Digital Solutions**
|
||||
|
|
|
|||
|
|
@ -1,85 +0,0 @@
|
|||
# V15 Soter pre-0x18 state snapshot
|
||||
|
||||
Date: 2026-08-27
|
||||
|
||||
Result: **PASS — diagnostic-only one-variable build; not flashed.**
|
||||
|
||||
Artifact SHA-256:
|
||||
`d2f542f8d475bc3699487647a041e16235f20847ee43d23e5545b55e6f2b8b1c`
|
||||
|
||||
Artifact size: 67,108,864 bytes.
|
||||
|
||||
## Hypothesis and change scope
|
||||
|
||||
The retained V14 property dump did not prove the exact values of seven public
|
||||
Microtrust/Soter properties at the instant immediately before the first cmd 0x18.
|
||||
|
||||
The only functional source delta from V14 is in
|
||||
`system/vold/Keymaster.cpp::Keymaster::exportKey()`: immediately after the existing
|
||||
length/SHA-256 checkpoint B and before
|
||||
`securityLevel->convertStorageKeyToEphemeral()`, recovery reads and logs:
|
||||
|
||||
- `vendor.soter.teei.googlekey.status`
|
||||
- `vendor.soter.teei.init`
|
||||
- `vendor.soter.teei.km.init`
|
||||
- `vendor.soter.teei.km.version`
|
||||
- `vendor.soter.teei.logini`
|
||||
- `vendor.soter.teei.persist`
|
||||
- `vendor.soter.teei.rpmb.flag`
|
||||
|
||||
The marker is `SYCA_SOTER_PRE_0X18`. The patch sets no property, changes no
|
||||
service ordering, changes no request bytes, and exposes no key material.
|
||||
|
||||
## Final-image differential
|
||||
|
||||
Against the preserved pre-V15 current recovery fragment, complete unpacked-file
|
||||
SHA-256 manifests differ only at:
|
||||
|
||||
- `system/bin/recovery`
|
||||
- before: `439d1fa5a5080e3ff5f293d18deb1e34aa21b48dc9ba9fd01e7e982fa83840e3`
|
||||
- V15: `53683ad4e34ffb6ebe4ffb705037f224f62334d2e355b5359230cc60e106077a`
|
||||
- `ramdisk-files.sha256sum`
|
||||
- `ramdisk-files.txt`
|
||||
|
||||
The final recovery binary contains `SYCA_SOTER_PRE_0X18`, the requested property
|
||||
names, and the existing `SYCA_DEKEY_A/B` diagnostics.
|
||||
|
||||
## Frozen final-image hashes
|
||||
|
||||
- PLATFORM:
|
||||
`06738f638a745075511c571347c5511331dda16b84d1ee88cda160c2dc7ebb14`
|
||||
- DTB:
|
||||
`0e93b71aacf707a5fbb7a58eff73995b92d766a31a98d8d70e91f548c9e1d5af`
|
||||
- Beanpod:
|
||||
`e066ff6e4f0aaa803e6633aa8fad1f54335e5b969f6422fedc44f77b033851e9`
|
||||
- `libTEECommon.so`:
|
||||
`d700e663bd3f68611cadef9bfc929aeb819e199cc9ef3f61a9c8d0afc2bed5b0`
|
||||
- KeyMint TA:
|
||||
`af4d1dc971c80b539de9e73ee792285944dd9b132d267be3bb0496bd82bb75ab`
|
||||
- `teei_daemon`:
|
||||
`fb79a0c59dab04edbf5ff4cd10af601c4d3dba5378b5ba3d981553f818fbb014`
|
||||
- `libteei_daemon_vfs.so`:
|
||||
`6012c5ccb298a411c8f7c0572b26ca237c3209ad348cd6e509a2cf71f4fccc13`
|
||||
- Keystore2:
|
||||
`31a9f7d9de497e06c465343ddb4d3aa3e8064c3051059c206b53d061d59f6256`
|
||||
- `libkeystore2_crypto.so`:
|
||||
`6e46dbfbf135c41131d64b91ce93fedf7c62077059fdbc24a5ca62b94e195132`
|
||||
|
||||
## vendor_boot audit
|
||||
|
||||
- header v4; page size 4096
|
||||
- cmdline: `bootopt=64S3,32N2,64N2`
|
||||
- fragment 0: exact stock PLATFORM, 27,422,144 bytes
|
||||
- fragment 1: RECOVERY named `recovery`, 31,678,798 bytes
|
||||
- total vendor ramdisk: 59,100,942 bytes
|
||||
- stock DTB exact
|
||||
- bootconfig empty
|
||||
- PLATFORM first, RECOVERY second
|
||||
- all board_id words zero
|
||||
- recovery fragment `.ko` count: zero
|
||||
- only five expected module metadata files retained
|
||||
- algorithm-NONE AVB footer and vendor_boot hash verify
|
||||
- post-AVB image re-unpacks successfully
|
||||
- final size exactly 67,108,864 bytes
|
||||
|
||||
Static audit: **PASS. Stop before flashing.**
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
# V16 boot-decrypt-unlock static audit
|
||||
|
||||
Date: 2026-08-27
|
||||
|
||||
Result: **PASS — one-variable boot-decrypt lifecycle experiment; not flashed.**
|
||||
|
||||
Artifact SHA-256:
|
||||
`1fe86baa602403638e2f0c0b2b7a29bc4cd768ec2bed9256b12aa92c8ca81e09`
|
||||
|
||||
Artifact size: 67,108,864 bytes.
|
||||
|
||||
## Hypothesis
|
||||
|
||||
The exact stock `teei_daemon` snapshots `ro.crypto.state` and
|
||||
`ro.crypto.type` in its boot-decrypt thread. With `ro.crypto.type=file`, it
|
||||
logs `fbe mode late` and issues the `/dev/teei_config` boot-decrypt-unlock
|
||||
ioctl. V15 did not expose that initial FBE state and never set
|
||||
`vendor.soter.teei.logini=start`; consequently it showed neither the daemon
|
||||
unlock message nor a boot-decrypt-lock result before cmd 0x18.
|
||||
|
||||
V16 tests whether reproducing those stock lifecycle inputs before the first
|
||||
storage-key conversion changes cmd 0x18 from `KM_ERROR_INVALID_KEY_BLOB`.
|
||||
|
||||
## Exact source changes
|
||||
|
||||
- `device/motorola/sycamore_row_5G/device.mk:16-22`
|
||||
- adds `ro.crypto.state=encrypted` and `ro.crypto.type=file` through
|
||||
`PRODUCT_SYSTEM_DEFAULT_PROPERTIES`, placing both in the initial recovery
|
||||
`prop.default` before `teei_daemon` starts.
|
||||
- `device/motorola/sycamore_row_5G/recovery/root/init.recovery.crypto.rc:69-73`
|
||||
- sets `vendor.soter.teei.logini=start` once the existing Soter init,
|
||||
persist-VFS, and RPMB health properties simultaneously report their stock
|
||||
terminal values.
|
||||
- `system/vold/Keymaster.cpp:187-213`
|
||||
- adds the secret-free `SYCA_V16_PRE_0X18` state snapshot immediately before
|
||||
`convertStorageKeyToEphemeral()`; V15 tracing remains present.
|
||||
|
||||
No other functional source was changed for V16. Cmd 0x18 serialization,
|
||||
wrapped-key bytes, Beanpod, TA, private libraries, SharedSecret, patch levels,
|
||||
DTB, PLATFORM, and kernel modules are unchanged.
|
||||
|
||||
## Implemented ordering
|
||||
|
||||
1. Initial property load exposes the real recovery FBE mode:
|
||||
`ro.crypto.state=encrypted`, `ro.crypto.type=file`.
|
||||
2. `on init` prepares the existing TEE device nodes and starts the exact stock
|
||||
`teei_daemon`.
|
||||
3. `init.svc.teei_daemon=running` starts Beanpod and Gatekeeper as in V15.
|
||||
4. Once `vendor.soter.teei.init=INIT_OK`,
|
||||
`vendor.soter.teei.persist=OPEN`, and
|
||||
`vendor.soter.teei.rpmb.flag=ok` are all true, init sets
|
||||
`vendor.soter.teei.logini=start`.
|
||||
5. Existing vold flow reaches the first storage-key conversion, where V16 logs
|
||||
the complete pre-0x18 public-state snapshot.
|
||||
|
||||
No sleep or repeated trigger was added. `vold.post_fs_data_done` and
|
||||
`vendor.soter.teei.crypto.state` were not set: the exact daemon does not
|
||||
reference the former, and its `ro.crypto.type=file` startup branch does not
|
||||
require the latter.
|
||||
|
||||
## Final recovery-fragment differential against archived V15
|
||||
|
||||
Complete relative-path SHA-256 manifests differ only at:
|
||||
|
||||
- `init.recovery.crypto.rc` (intentional logini trigger)
|
||||
- `prop.default` (intentional two FBE defaults)
|
||||
- `system/bin/recovery` (intentional V16 marker)
|
||||
- `ramdisk-files.sha256sum` and `ramdisk-files.txt` (generated inventory)
|
||||
|
||||
There are no added or removed payload paths.
|
||||
|
||||
## Frozen binary/content verification
|
||||
|
||||
- stock PLATFORM:
|
||||
`06738f638a745075511c571347c5511331dda16b84d1ee88cda160c2dc7ebb14`
|
||||
- stock DTB:
|
||||
`0e93b71aacf707a5fbb7a58eff73995b92d766a31a98d8d70e91f548c9e1d5af`
|
||||
- exact stock `teei_daemon`:
|
||||
`fb79a0c59dab04edbf5ff4cd10af601c4d3dba5378b5ba3d981553f818fbb014`
|
||||
- Beanpod:
|
||||
`e066ff6e4f0aaa803e6633aa8fad1f54335e5b969f6422fedc44f77b033851e9`
|
||||
- KeyMint TA:
|
||||
`af4d1dc971c80b539de9e73ee792285944dd9b132d267be3bb0496bd82bb75ab`
|
||||
- Keystore2:
|
||||
`31a9f7d9de497e06c465343ddb4d3aa3e8064c3051059c206b53d061d59f6256`
|
||||
- `libkeystore2_crypto.so`:
|
||||
`6e46dbfbf135c41131d64b91ce93fedf7c62077059fdbc24a5ca62b94e195132`
|
||||
|
||||
All nine stock KeyMint private-library hashes and the V15 keytrace library hash
|
||||
match the frozen V15 family. The recovery fragment contains zero `.ko` files
|
||||
and only the same five module metadata files.
|
||||
|
||||
## Final vendor_boot audit
|
||||
|
||||
- header version 4; page size 4096
|
||||
- command line `bootopt=64S3,32N2,64N2`
|
||||
- bootconfig empty
|
||||
- fragment 0: unnamed PLATFORM, type 1, 27,422,144 bytes, exact stock hash
|
||||
- fragment 1: `recovery`, RECOVERY type 2, 31,679,640 bytes
|
||||
- total vendor ramdisk size: 59,101,784 bytes
|
||||
- all board IDs zero; PLATFORM first and RECOVERY second
|
||||
- exact stock DTB, 192,119 bytes
|
||||
- algorithm-NONE AVB footer verifies
|
||||
- final image re-unpacks successfully
|
||||
- final partition-padded size exactly 67,108,864 bytes
|
||||
|
||||
## Expected hardware-test markers
|
||||
|
||||
- `SYCA_V16_PRE_0X18`
|
||||
- `daemon unlock keymaster signal to tz-driver`
|
||||
- `keymaster unlock boot_decrypt_lock success` or `failed!`
|
||||
- existing `SYCA_SOTER_PRE_0X18`, `SYCA_DEKEY_A/B/C/D`, `SYCA_TA_TRACE`,
|
||||
cmd 0x18 hashes, and cmd result
|
||||
|
||||
Static audit: **PASS. Stop before flashing.**
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
# V17 stock THH identity static audit
|
||||
|
||||
Date: 2026-08-27
|
||||
|
||||
Result: **PASS — controlled stock-THH/product-identity experiment; not flashed.**
|
||||
|
||||
Artifact SHA-256:
|
||||
`f23330a09d0b0ea4a7c902342dd62f36dcf5179cd72ed40d316819deb7c9ec50`
|
||||
|
||||
Artifact size: 67,108,864 bytes.
|
||||
|
||||
## Hypothesis
|
||||
|
||||
V16 initialized Microtrust with an incomplete `/vendor/thh/ta` namespace and
|
||||
the recovery codename as `ro.product.device`. The exact signed stock model
|
||||
configuration recognizes `platform=mt8755`, `model=XT2575-4`, while V16 secure
|
||||
world logged `model:sycamore_row_5G`, model verification failures, and TA load
|
||||
error 18. V17 tests whether presenting the complete exact-stock THH payload
|
||||
and production Microtrust-facing identity before the first `teei_daemon`
|
||||
launch restores cold TA/model validation and changes cmd 0x18 behavior.
|
||||
|
||||
All V16 FBE/logini behavior and crypto diagnostics are retained unchanged.
|
||||
|
||||
## Exact stock source
|
||||
|
||||
The files were copied from the preserved exact-firmware vendor extraction:
|
||||
|
||||
`/home/nicholas/Downloads/sycamore-twrp-info/first-hardware-boot/fbe-a16-v3/ta-forensics/stock-vendor-thh/ta`
|
||||
|
||||
This extraction belongs to factory baseline
|
||||
`XT2575-4_ROW_OPEN_USER_M1317.3_W_ZUI_17.5.10.017_ST`. Both the staged source
|
||||
tree and the final unpacked recovery fragment were compared byte-for-byte with
|
||||
all 15 source files. Both comparisons pass.
|
||||
|
||||
## Stock THH manifest
|
||||
|
||||
| File | Bytes | SHA-256 |
|
||||
|---|---:|---|
|
||||
| `0102030405060708090a0b0c0d0e0f10.ta` | 20,777 | `19a5e15a2f17a6c1418c5edc6fc63a3ddd279966540930b2e97f227ce0d897ae` |
|
||||
| `020f0000000000000000000000000000.ta` | 22,649 | `aba910dfbdccbf177eb107853669c6eff689b4f36e9afb2f8e04e30d8e97108b` |
|
||||
| `06090000000000000000000000000000.ta` | 6,953 | `2d5cd2e906a1dab1636c59bbe037f8502aec7c25edc9172cba8da158fc6d8c36` |
|
||||
| `08030000000000000000000000000000.ta` | 24,393 | `ba29286b7d24edc04275b195db120032e116828ff73241241d6d8c40855b4f03` |
|
||||
| `08110000000000000000000000000000.ta` | 72,073 | `0fb3e0b70a972d4a58088978aec706399009f32f5133061efe6b7033f1ae9f17` |
|
||||
| `40188311faf343488db888ad39496f9a.ta` | 9,177 | `5cb79b594721523700fe4708ea764c80144979dc698db27a18a2383159028a1c` |
|
||||
| `5020170115e016302017012521300000.ta` | 10,393 | `0865a891c965a201d4e64f3b9e2f4a3f0fe899f80ff24ab88cf75b1622dc5d40` |
|
||||
| `5f7a5b3b29b041bca249524a031a00e3.ta` | 32,737 | `2911bd3726ae4110877409d501329f36f5958a6686262b93814d8bb89fdb629c` |
|
||||
| `8888c04fc30c4dd0a319ea29643d4d4c.ta` | 32,129 | `5b812b524f5eea79c1bc944b06d00cddc8738274166d888bf255080ab0feab09` |
|
||||
| `abcd270ea5c44c58bcd3384a2fa2539e.ta` | 39,833 | `c4d5811efd695ba0550960f9c5649e6476289cbb00cb8c9d7f5cb11b7a2e2f18` |
|
||||
| `c09c9c5daa504b78b0e46eda61556c3a.ta` | 930,857 | `af4d1dc971c80b539de9e73ee792285944dd9b132d267be3bb0496bd82bb75ab` |
|
||||
| `c1882f2d885e4e13a8c8e2622461b2fa.ta` | 55,537 | `0a5f34be1d73535c563aaece231b2e93193ae5f2c69b8050e71b14f48956081d` |
|
||||
| `d91f322ad5a441d5955110eda3272fc0.ta` | 22,177 | `4432d3f85370e41f57bf5fb6b5945326c441a394d0cbe298be5c29b2b056b954` |
|
||||
| `e97c270ea5c44c58bcd3384a2fa2539e.ta` | 447,769 | `c76352a8115aba85e963d2e39466530daa8ac5db411ccea403eaf84d2c308e96` |
|
||||
| `isee_model.json` | 2,794 | `67c019209942f9a68408d998e5d478b0dba5e3f5dbbc6582b146af8aaa05e3c6` |
|
||||
|
||||
## Source/change scope
|
||||
|
||||
- `device/motorola/sycamore_row_5G/device.mk`
|
||||
- packages all 15 stock THH files and the early diagnostic script;
|
||||
- adds only global `ro.product.device=XT2575-4` to the existing V16 initial
|
||||
system-default property set.
|
||||
- `build/make/core/Makefile`
|
||||
- recovery-only, target-gated, fail-closed replacement of the two generated
|
||||
vendor device/name values in final `prop.default`; vendor model was already
|
||||
stock-correct.
|
||||
- `device/motorola/sycamore_row_5G/recovery/root/init.recovery.crypto.rc`
|
||||
- synchronously executes the readiness diagnostic immediately before the
|
||||
existing first `start teei_daemon`.
|
||||
- `device/motorola/sycamore_row_5G/recovery/root/system/bin/syca_v17_thh_ready.sh`
|
||||
- logs only public properties, four existence results, and total file count.
|
||||
- fourteen stock THH files were added under
|
||||
`device/motorola/sycamore_row_5G/recovery/root/vendor/thh/ta`; the fifteenth,
|
||||
the KeyMint TA, was already present and byte-identical.
|
||||
|
||||
## Final initial properties
|
||||
|
||||
- `ro.product.device=XT2575-4`
|
||||
- `ro.product.vendor.device=XT2575-4`
|
||||
- `ro.product.vendor.name=XT2575-4`
|
||||
- `ro.product.vendor.model=XT2575-4`
|
||||
- `ro.build.product=sycamore_row_5G` (preserved)
|
||||
- `ro.crypto.type=file` (V16 preserved)
|
||||
- `ro.crypto.state=encrypted` (V16 preserved)
|
||||
|
||||
`PRODUCT_DEVICE=sycamore_row_5G`, the TWRP product name, target assertions, and
|
||||
`ro.twrp.target.devices` behavior were not changed.
|
||||
|
||||
## Cold-boot ordering
|
||||
|
||||
1. Recovery ramdisk, all 15 THH files, production identity, and V16 FBE
|
||||
properties exist before init actions.
|
||||
2. Existing TEE/RPMB nodes and read-only persist mount are prepared.
|
||||
3. Init synchronously runs `syca_v17_thh_ready.sh` and emits
|
||||
`SYCA_V17_THH_READY`; expected `thh_file_count=15`.
|
||||
4. Init launches the unchanged exact-stock `teei_daemon` for the first time.
|
||||
5. The daemon performs cold secure-world TA/model validation.
|
||||
6. Existing `init.svc.teei_daemon=running` action starts Beanpod/Gatekeeper.
|
||||
7. Existing V16 healthy-state conjunction sets `logini=start`.
|
||||
8. Existing vold/Keystore2 path reaches the first cmd 0x18.
|
||||
|
||||
No sleep, restart, bind mount, or post-initialization substitution was added.
|
||||
|
||||
## V16-to-V17 final-image differential
|
||||
|
||||
Complete unpacked relative-path SHA-256 manifests show only:
|
||||
|
||||
- modified: `init.recovery.crypto.rc`, `prop.default`, and generated ramdisk
|
||||
inventory files;
|
||||
- added: readiness script and the 14 THH files absent from V16;
|
||||
- unchanged: `system/bin/recovery`, existing KeyMint TA, all secure binaries,
|
||||
private libraries, Keytrace, and every other ramdisk payload.
|
||||
|
||||
## Frozen architecture/binary verification
|
||||
|
||||
- stock PLATFORM:
|
||||
`06738f638a745075511c571347c5511331dda16b84d1ee88cda160c2dc7ebb14`
|
||||
- stock DTB:
|
||||
`0e93b71aacf707a5fbb7a58eff73995b92d766a31a98d8d70e91f548c9e1d5af`
|
||||
- exact stock `teei_daemon`:
|
||||
`fb79a0c59dab04edbf5ff4cd10af601c4d3dba5378b5ba3d981553f818fbb014`
|
||||
- Beanpod:
|
||||
`e066ff6e4f0aaa803e6633aa8fad1f54335e5b969f6422fedc44f77b033851e9`
|
||||
- KeyMint TA:
|
||||
`af4d1dc971c80b539de9e73ee792285944dd9b132d267be3bb0496bd82bb75ab`
|
||||
- Keystore2:
|
||||
`31a9f7d9de497e06c465343ddb4d3aa3e8064c3051059c206b53d061d59f6256`
|
||||
- `libkeystore2_crypto.so`:
|
||||
`6e46dbfbf135c41131d64b91ce93fedf7c62077059fdbc24a5ca62b94e195132`
|
||||
- Keytrace:
|
||||
`0642e36b25589ebdf16423cb3a81c8ba5dab3ffc0dcb32a58386efa8b2d7293d`
|
||||
|
||||
The final recovery has zero `.ko` files and the same five module metadata
|
||||
files. V16 `SYCA_V16_PRE_0X18`, `SYCA_SOTER_PRE_0X18`,
|
||||
`SYCA_DEKEY_A/B/C/D`, and `SYCA_TA_TRACE` markers remain present.
|
||||
|
||||
## Final vendor_boot audit
|
||||
|
||||
- header v4; page size 4096
|
||||
- cmdline `bootopt=64S3,32N2,64N2`; bootconfig empty
|
||||
- fragment 0: unnamed PLATFORM/type 1, 27,422,144 bytes, exact stock hash
|
||||
- fragment 1: `recovery`/type 2, 32,078,301 bytes
|
||||
- total vendor ramdisk: 59,500,445 bytes
|
||||
- stock DTB exact; all board IDs zero
|
||||
- PLATFORM first, RECOVERY second
|
||||
- algorithm-NONE AVB footer and vendor_boot hash verify
|
||||
- final image re-unpacks successfully
|
||||
- final partition-padded size exactly 67,108,864 bytes
|
||||
|
||||
Static audit: **PASS. Stop before flashing.**
|
||||
|
|
@ -1,177 +0,0 @@
|
|||
# V18.1 cold stock tee identity static audit
|
||||
|
||||
Date: 2026-08-27
|
||||
|
||||
Result: **PASS — surgical init/DAC/tee-permissive experiment; not flashed.**
|
||||
|
||||
Immutable baseline:
|
||||
`fbe-a16-v18-stock-tee-identity`
|
||||
|
||||
Baseline SHA-256:
|
||||
`7c6817d5b29055ac337b26a87e3c29281e8ff2df2209521546c75bb8064642ac`
|
||||
|
||||
V18.1 artifact SHA-256:
|
||||
`5f57030d1cd10d6ef0c3987c8a1b3119f7e51ef23ddc21f647970cf4efb6a26d`
|
||||
|
||||
Artifact size: 67,108,864 bytes.
|
||||
|
||||
## Task-scoped source changes
|
||||
|
||||
- `device/motorola/sycamore_row_5G/recovery/root/init.recovery.crypto.rc`
|
||||
- moves exact stock Microtrust DAC and first daemon start to `on fs`;
|
||||
- restores the daemon executable context before starting it;
|
||||
- gates Beanpod/Gatekeeper on `vendor.soter.teei.init=INIT_OK`;
|
||||
- uses stock `post-fs-data` logini lifecycle.
|
||||
- `device/motorola/sycamore_row_5G/sepolicy/vendor/teei_device.te`
|
||||
- adds only `permissive tee;` for this diagnostic build.
|
||||
|
||||
No other source file was modified for V18.1.
|
||||
|
||||
Task-scoped diff stat:
|
||||
|
||||
```text
|
||||
recovery/root/init.recovery.crypto.rc | 48 +++++++++++++++++++++++++++--------
|
||||
sepolicy/vendor/teei_device.te | 4 +++
|
||||
2 files changed, 41 insertions(+), 11 deletions(-)
|
||||
```
|
||||
|
||||
## A. teei_daemon service
|
||||
|
||||
The final unpacked recovery contains the complete V18 `-r`/`-t` UUID sequence
|
||||
unchanged and exactly:
|
||||
|
||||
```rc
|
||||
user system
|
||||
group system
|
||||
disabled
|
||||
capabilities SYS_RAWIO
|
||||
seclabel u:r:tee:s0
|
||||
```
|
||||
|
||||
There is one primary `group system` declaration and no supplementary group.
|
||||
`SYS_RAWIO` is the only capability. The final daemon binary is byte-identical
|
||||
to V18:
|
||||
|
||||
`fb79a0c59dab04edbf5ff4cd10af601c4d3dba5378b5ba3d981553f818fbb014`
|
||||
|
||||
## B. executable runtime context
|
||||
|
||||
Final `vendor_file_contexts` still contains:
|
||||
|
||||
```text
|
||||
/vendor/bin/teei_daemon u:object_r:tee_exec:s0
|
||||
```
|
||||
|
||||
The final init action executes:
|
||||
|
||||
```rc
|
||||
on fs
|
||||
restorecon /vendor/bin/teei_daemon
|
||||
...
|
||||
start teei_daemon
|
||||
```
|
||||
|
||||
`restorecon` precedes every Microtrust DAC operation and the first daemon start.
|
||||
|
||||
## C. exact stock DAC sequence
|
||||
|
||||
The final `on fs` action contains, in the requested order:
|
||||
|
||||
```rc
|
||||
restorecon /vendor/bin/teei_daemon
|
||||
chmod 0660 /dev/teei_client
|
||||
chown system system /dev/teei_client
|
||||
chmod 0660 /dev/teei_config
|
||||
chown system system /dev/teei_config
|
||||
chmod 0666 /dev/isee_tee0
|
||||
chown system drmrpc /dev/isee_tee0
|
||||
chmod 0660 /dev/tz_vfs
|
||||
chown system system /dev/tz_vfs
|
||||
chmod 0660 /dev/teei_fp
|
||||
chown system /dev/teei_fp
|
||||
chown system drmrpc /dev/ut_keymaster
|
||||
chmod 0660 /dev/ut_keymaster
|
||||
chmod 0660 /dev/0:0:0:49476
|
||||
chown system system /dev/0:0:0:49476
|
||||
chmod 0660 /dev/rpmb0
|
||||
chown system system /dev/rpmb0
|
||||
chmod 0660 /dev/emmcrpmb0
|
||||
chown system system /dev/emmcrpmb0
|
||||
chown system system /dev/utr_tui
|
||||
chmod 0660 /dev/utr_tui
|
||||
start teei_daemon
|
||||
```
|
||||
|
||||
No node is manufactured. `/dev/teeperf` remains separately handled in
|
||||
`on init` at mode 0660.
|
||||
|
||||
The persist setup remains byte-for-byte equivalent to V18:
|
||||
|
||||
```rc
|
||||
mkdir /mnt/vendor/persist 0771 system system
|
||||
mount ext4 /dev/block/sdc14 /mnt/vendor/persist ro noatime nosuid nodev wait noload
|
||||
```
|
||||
|
||||
## D. sequencing
|
||||
|
||||
- no `init.svc.teei_daemon=running` action starts security services;
|
||||
- `vendor.soter.teei.init=INIT_OK` starts Beanpod and Gatekeeper;
|
||||
- `on post-fs-data` sets `vendor.soter.teei.logini=start`;
|
||||
- no init property action sets `vendor.soter.teei.persist` or
|
||||
`vendor.soter.teei.rpmb.flag`;
|
||||
- no sleep was introduced.
|
||||
|
||||
## E. SELinux
|
||||
|
||||
The final compiled-policy permissive-domain set differs from V18 by exactly one
|
||||
entry: `tee`. Existing recovery-build permissive domains are unchanged.
|
||||
|
||||
`tee` is intentionally permissive for V18.1. Global kernel/recovery enforcing
|
||||
configuration was not changed, no other domain was added, existing node types
|
||||
and allow rules were preserved, and policy/neverallow compilation passed.
|
||||
|
||||
Final policy SHA-256:
|
||||
`5d9a65cc5a28d3f7ef8ca79f1a40ba4d2548b91a6be0f115085df54b3ae7d055`
|
||||
|
||||
## F. frozen crypto comparison against V18
|
||||
|
||||
Complete unpacked-file manifests differ only at:
|
||||
|
||||
- `init.recovery.crypto.rc`;
|
||||
- `sepolicy`;
|
||||
- generated `ramdisk-files.sha256sum` and `ramdisk-files.txt`.
|
||||
|
||||
Everything else is byte-identical, including:
|
||||
|
||||
| Payload | SHA-256 |
|
||||
|---|---|
|
||||
| `teei_daemon` | `fb79a0c59dab04edbf5ff4cd10af601c4d3dba5378b5ba3d981553f818fbb014` |
|
||||
| Beanpod | `e066ff6e4f0aaa803e6633aa8fad1f54335e5b969f6422fedc44f77b033851e9` |
|
||||
| Gatekeeper | `7460ce26460376b24c29d2f46820ecc5646505fe24090f57aa7d05141e77d3b9` |
|
||||
| Keymaster TA | `af4d1dc971c80b539de9e73ee792285944dd9b132d267be3bb0496bd82bb75ab` |
|
||||
| diagnostic preload | `0642e36b25589ebdf16423cb3a81c8ba5dab3ffc0dcb32a58386efa8b2d7293d` |
|
||||
| Keystore2 | `31a9f7d9de497e06c465343ddb4d3aa3e8064c3051059c206b53d061d59f6256` |
|
||||
| `libkeystore2_crypto.so` | `6e46dbfbf135c41131d64b91ce93fedf7c62077059fdbc24a5ca62b94e195132` |
|
||||
| cmd0x18-bearing recovery binary | `986d25bac8ceb0df6edee2731c5b92c30090f30c84977229022e33c97e9a3a89` |
|
||||
|
||||
All eight private KeyMint libraries compare byte-for-byte with V18. The full
|
||||
15-file THH directory, including `isee_model.json`, compares byte-for-byte with
|
||||
V18. Product/model/platform and FBE property subsets are identical to V18.
|
||||
|
||||
## G. stock hybrid / final image
|
||||
|
||||
- header v4; page size 4096
|
||||
- cmdline `bootopt=64S3,32N2,64N2`; bootconfig empty
|
||||
- fragment 0: unnamed PLATFORM/type 1, 27,422,144 bytes
|
||||
- PLATFORM SHA-256:
|
||||
`06738f638a745075511c571347c5511331dda16b84d1ee88cda160c2dc7ebb14`
|
||||
- fragment 1: `recovery`/type 2, 32,078,214 bytes
|
||||
- total vendor ramdisk: 59,500,358 bytes
|
||||
- DTB SHA-256:
|
||||
`0e93b71aacf707a5fbb7a58eff73995b92d766a31a98d8d70e91f548c9e1d5af`
|
||||
- recovery `.ko` count: zero; same five module metadata files
|
||||
- algorithm-NONE AVB footer and vendor_boot hash verify
|
||||
- image re-unpacks successfully
|
||||
- final size exactly 67,108,864 bytes
|
||||
|
||||
Static audit: **PASS. Stop before flashing.**
|
||||
|
|
@ -1,158 +0,0 @@
|
|||
# V18 stock tee identity static audit
|
||||
|
||||
Date: 2026-08-27
|
||||
|
||||
Result: **PASS — controlled teei_daemon execution-identity experiment; not flashed.**
|
||||
|
||||
Artifact SHA-256:
|
||||
`7c6817d5b29055ac337b26a87e3c29281e8ff2df2209521546c75bb8064642ac`
|
||||
|
||||
Artifact size: 67,108,864 bytes.
|
||||
|
||||
## Hypothesis
|
||||
|
||||
V17 fixed cold THH/model validation but still ran the unchanged stock
|
||||
`teei_daemon` as root in `u:r:recovery:s0`. V18 tests whether the missing
|
||||
boot-decrypt-unlock transition and cmd 0x18 key-blob failure depend on the
|
||||
daemon's production process identity: UID/GID 1000, no supplementary groups,
|
||||
only `CAP_SYS_RAWIO`, and enforcing `u:r:tee:s0`.
|
||||
|
||||
No KeyMint, wrapped-key, FBE, secure-storage, vendor_boot, kernel, or binary
|
||||
behavior was otherwise changed.
|
||||
|
||||
## Service declaration differential
|
||||
|
||||
V17:
|
||||
|
||||
```rc
|
||||
user root
|
||||
group root system
|
||||
capabilities SYS_RAWIO
|
||||
seclabel u:r:recovery:s0
|
||||
```
|
||||
|
||||
V18:
|
||||
|
||||
```rc
|
||||
user system
|
||||
group system
|
||||
capabilities SYS_RAWIO
|
||||
seclabel u:r:tee:s0
|
||||
```
|
||||
|
||||
The complete 21-entry `-r`/`-t` UUID argument sequence is byte-for-byte
|
||||
unchanged. A single `group system` entry establishes the primary GID only; no
|
||||
supplementary group is declared. `SYS_RAWIO` is the sole capability token.
|
||||
|
||||
## SELinux audit and implementation
|
||||
|
||||
The pre-V18 platform policy already defined:
|
||||
|
||||
- `tee` with the `domain` attribute;
|
||||
- `tee_exec` as an executable vendor-file type;
|
||||
- `init_daemon_domain(tee)`, producing
|
||||
`type_transition init tee_exec:process tee`.
|
||||
|
||||
V17 lacked a `tee_exec` path label for `/vendor/bin/teei_daemon`, so merely
|
||||
changing `seclabel` could not prove a valid launch environment.
|
||||
|
||||
V18 adds the exact executable context and the narrowly scoped stock Microtrust
|
||||
device contexts under `device/motorola/sycamore_row_5G/sepolicy/vendor`. The
|
||||
final combined policy:
|
||||
|
||||
- compiles successfully;
|
||||
- passes neverallow checks;
|
||||
- contains `tee` in the `domain` attribute;
|
||||
- contains the init→`tee` transition;
|
||||
- permits `tee` to use only the declared Microtrust node types;
|
||||
- permits `tee` `sys_rawio` capability use;
|
||||
- does **not** mark `tee` permissive.
|
||||
|
||||
Final policy SHA-256:
|
||||
`0b23e52b72848a03649e78fe005b88827d35a37bcab2ce8d394fc6d395fd94d3`
|
||||
|
||||
## Exact node contexts
|
||||
|
||||
These are copied from the exact stock vendor_boot `vendor_file_contexts`:
|
||||
|
||||
| Path | Final type |
|
||||
|---|---|
|
||||
| `/dev/isee_tee0` | `teei_client_device` |
|
||||
| `/dev/teei_client` | `teei_client_device` |
|
||||
| `/dev/teei_config` | `teei_config_device` |
|
||||
| `/dev/tz_vfs` | `teei_vfs_device` |
|
||||
| `/dev/teei_fp` | `teei_fp_device` |
|
||||
| `/dev/ut_keymaster` | `ut_keymaster_device` |
|
||||
| `/dev/0:0:0:49476` | `teei_rpmb_device` |
|
||||
| `/dev/rpmb0` | `teei_rpmb_device` |
|
||||
| `/dev/utr_tui` | `utr_tui_device` |
|
||||
| `/vendor/bin/teei_daemon` | `tee_exec` |
|
||||
|
||||
No non-Microtrust device path was relabeled. These labels are required for the
|
||||
enforcing `tee` domain to use the same interfaces that V17 accessed from the
|
||||
permissive recovery domain.
|
||||
|
||||
## Removed failed V17 diagnostic
|
||||
|
||||
The packaged `syca_v17_thh_ready.sh` and its synchronous init `exec` were
|
||||
removed. This eliminates the known invalid-domain exec failure and does not add
|
||||
a replacement delay or process. V16/V17 crypto diagnostics remain intact.
|
||||
|
||||
## Frozen V17/V16 state
|
||||
|
||||
- all 15 stock THH files: byte-identical to the exact stock extraction;
|
||||
- `isee_model.json`: unchanged;
|
||||
- `ro.product.device=XT2575-4`;
|
||||
- all three vendor product identity fields: `XT2575-4`;
|
||||
- `ro.build.product=sycamore_row_5G`;
|
||||
- `ro.crypto.type=file` and `ro.crypto.state=encrypted`;
|
||||
- healthy-state `vendor.soter.teei.logini=start` ordering;
|
||||
- `SYCA_V16_PRE_0X18`, `SYCA_SOTER_PRE_0X18`,
|
||||
`SYCA_DEKEY_A/B/C/D`, and `SYCA_TA_TRACE`.
|
||||
|
||||
## Frozen hashes
|
||||
|
||||
- stock PLATFORM:
|
||||
`06738f638a745075511c571347c5511331dda16b84d1ee88cda160c2dc7ebb14`
|
||||
- stock DTB:
|
||||
`0e93b71aacf707a5fbb7a58eff73995b92d766a31a98d8d70e91f548c9e1d5af`
|
||||
- exact stock `teei_daemon`:
|
||||
`fb79a0c59dab04edbf5ff4cd10af601c4d3dba5378b5ba3d981553f818fbb014`
|
||||
- Beanpod:
|
||||
`e066ff6e4f0aaa803e6633aa8fad1f54335e5b969f6422fedc44f77b033851e9`
|
||||
- KeyMint TA:
|
||||
`af4d1dc971c80b539de9e73ee792285944dd9b132d267be3bb0496bd82bb75ab`
|
||||
- Keystore2:
|
||||
`31a9f7d9de497e06c465343ddb4d3aa3e8064c3051059c206b53d061d59f6256`
|
||||
- Keytrace:
|
||||
`0642e36b25589ebdf16423cb3a81c8ba5dab3ffc0dcb32a58386efa8b2d7293d`
|
||||
|
||||
## V17-to-V18 final-image differential
|
||||
|
||||
Complete unpacked relative-path SHA-256 manifests differ only at:
|
||||
|
||||
- `init.recovery.crypto.rc` — intended service identity and failed-diagnostic
|
||||
removal;
|
||||
- `sepolicy`, `vendor_file_contexts`, and `file_contexts.bin` — intended narrow
|
||||
tee-domain implementation;
|
||||
- removal of `system/bin/syca_v17_thh_ready.sh`;
|
||||
- generated ramdisk inventory files.
|
||||
|
||||
No secure binary, THH payload, property file, kernel module, or crypto
|
||||
diagnostic binary changed.
|
||||
|
||||
## Final vendor_boot audit
|
||||
|
||||
- header v4; page size 4096
|
||||
- cmdline `bootopt=64S3,32N2,64N2`; bootconfig empty
|
||||
- fragment 0: unnamed PLATFORM/type 1, 27,422,144 bytes, exact stock hash
|
||||
- fragment 1: `recovery`/type 2, 32,078,200 bytes
|
||||
- total vendor ramdisk: 59,500,344 bytes
|
||||
- exact stock DTB; all board IDs zero
|
||||
- PLATFORM first, RECOVERY second
|
||||
- recovery `.ko` count: zero; same five module metadata files
|
||||
- algorithm-NONE AVB footer and vendor_boot hash verify
|
||||
- final image re-unpacks successfully
|
||||
- final partition-padded size exactly 67,108,864 bytes
|
||||
|
||||
Static audit: **PASS. Stop before flashing.**
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
# V19 stock Beanpod UID static audit
|
||||
|
||||
Date: 2026-08-27
|
||||
|
||||
Result: **PASS — one-line Beanpod Unix-identity experiment; not flashed.**
|
||||
|
||||
Immutable baseline:
|
||||
`fbe-a16-v18.1-cold-stock-tee-identity`
|
||||
|
||||
Baseline SHA-256:
|
||||
`5f57030d1cd10d6ef0c3987c8a1b3119f7e51ef23ddc21f647970cf4efb6a26d`
|
||||
|
||||
V19 artifact SHA-256:
|
||||
`549e214d0e58888e6d9b449fd9dafb3fa2912d76295bef18a1409e1ca60b761a`
|
||||
|
||||
Artifact size: 67,108,864 bytes.
|
||||
|
||||
## Hypothesis and exact change
|
||||
|
||||
V19 tests whether Microtrust KeyMint storage-key cmd 0x18 depends on Beanpod's
|
||||
stock Linux UID 9999. It intentionally retains the V18.1 recovery SELinux
|
||||
domain so the Unix identity is the only runtime variable.
|
||||
|
||||
The sole task source change is:
|
||||
|
||||
`device/motorola/sycamore_row_5G/recovery/root/init.recovery.crypto.rc`
|
||||
|
||||
```diff
|
||||
- user root
|
||||
+ user nobody
|
||||
```
|
||||
|
||||
Task-scoped V18.1-to-V19 diff stat:
|
||||
|
||||
```text
|
||||
init.recovery.crypto.rc | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
```
|
||||
|
||||
## 1–3. Final Beanpod service
|
||||
|
||||
The final unpacked ramdisk contains:
|
||||
|
||||
```rc
|
||||
service vendor.keymint-beanpod /vendor/bin/hw/android.hardware.security.keymint@2.0-service.beanpod
|
||||
class early_hal
|
||||
user nobody
|
||||
group root
|
||||
disabled
|
||||
seclabel u:r:recovery:s0
|
||||
setenv LD_LIBRARY_PATH /vendor/lib64:/vendor/lib64/hw:/system/lib64:/system/lib64/hw
|
||||
setenv LD_PRELOAD /vendor/lib64/libsycamore_keytrace.so
|
||||
```
|
||||
|
||||
There is no capability declaration and no supplementary group. Expected Linux
|
||||
credentials are UID 9999, primary GID 0, empty supplementary groups, and zero
|
||||
inheritable/permitted/effective/ambient capabilities.
|
||||
|
||||
## 4–7. Frozen secure payloads
|
||||
|
||||
Every listed final file compares byte-for-byte with the unpacked archived
|
||||
V18.1 baseline:
|
||||
|
||||
| Payload | SHA-256 |
|
||||
|---|---|
|
||||
| Beanpod | `e066ff6e4f0aaa803e6633aa8fad1f54335e5b969f6422fedc44f77b033851e9` |
|
||||
| `teei_daemon` | `fb79a0c59dab04edbf5ff4cd10af601c4d3dba5378b5ba3d981553f818fbb014` |
|
||||
| Gatekeeper | `7460ce26460376b24c29d2f46820ecc5646505fe24090f57aa7d05141e77d3b9` |
|
||||
| Keymaster TA | `af4d1dc971c80b539de9e73ee792285944dd9b132d267be3bb0496bd82bb75ab` |
|
||||
| diagnostic preload | `0642e36b25589ebdf16423cb3a81c8ba5dab3ffc0dcb32a58386efa8b2d7293d` |
|
||||
| Keystore2 | `31a9f7d9de497e06c465343ddb4d3aa3e8064c3051059c206b53d061d59f6256` |
|
||||
| `libkeystore2_crypto.so` | `6e46dbfbf135c41131d64b91ce93fedf7c62077059fdbc24a5ca62b94e195132` |
|
||||
| cmd0x18-bearing recovery binary | `986d25bac8ceb0df6edee2731c5b92c30090f30c84977229022e33c97e9a3a89` |
|
||||
|
||||
All eight private KeyMint libraries are byte-identical. The complete 15-file
|
||||
THH directory, including `isee_model.json`, is byte-identical.
|
||||
|
||||
## 8–11. Frozen ordering/configuration/diagnostics
|
||||
|
||||
Replacing the V18.1 `user root` line with `user nobody` produces a file
|
||||
byte-identical to V19 `init.recovery.crypto.rc`; therefore every other byte of
|
||||
the service definitions, UUID arguments, cold `on fs` DAC sequence, INIT_OK
|
||||
gate, post-fs-data logini action, persist mount, and RPMB handling is unchanged.
|
||||
|
||||
Final `prop.default`, compiled SELinux policy, and `vendor_file_contexts` are
|
||||
byte-identical to V18.1. This preserves:
|
||||
|
||||
- V18.1 tee-domain policy and permissive state;
|
||||
- all product/model/platform and FBE properties;
|
||||
- all Microtrust file contexts;
|
||||
- `SYCA_V16_PRE_0X18`, `SYCA_SOTER_PRE_0X18`,
|
||||
`SYCA_DEKEY_A/B/C/D`, and `SYCA_TA_TRACE` instrumentation.
|
||||
|
||||
## 12–16. Final vendor_boot audit
|
||||
|
||||
- header v4; page size 4096
|
||||
- cmdline `bootopt=64S3,32N2,64N2`; bootconfig empty
|
||||
- fragment 0: unnamed PLATFORM/type 1, 27,422,144 bytes
|
||||
- PLATFORM SHA-256:
|
||||
`06738f638a745075511c571347c5511331dda16b84d1ee88cda160c2dc7ebb14`
|
||||
- fragment 1: `recovery`/type 2, 32,078,223 bytes
|
||||
- total vendor ramdisk: 59,500,367 bytes
|
||||
- DTB SHA-256:
|
||||
`0e93b71aacf707a5fbb7a58eff73995b92d766a31a98d8d70e91f548c9e1d5af`
|
||||
- no kernel payload was changed; recovery `.ko` count is zero and the five
|
||||
module metadata filenames match V18.1
|
||||
- algorithm-NONE AVB footer and vendor_boot hash verify
|
||||
- final image re-unpacks successfully
|
||||
- final partition-padded size exactly 67,108,864 bytes
|
||||
|
||||
Complete final ramdisk manifests differ from V18.1 only at
|
||||
`init.recovery.crypto.rc` and the two generated ramdisk inventory files.
|
||||
|
||||
Static audit: **PASS. Stop before flashing.**
|
||||
|
|
@ -18,8 +18,7 @@ PRODUCT_SOONG_NAMESPACES += $(DEVICE_PATH)
|
|||
# passthrough stub while keeping the generic fastbootd logical-partition path.
|
||||
PRODUCT_PACKAGES += \
|
||||
android.hardware.fastboot@1.1-impl-mock \
|
||||
sycamore_boot_hal_stock_libbase \
|
||||
sycamore_fscryptd
|
||||
sycamore_boot_hal_stock_libbase
|
||||
|
||||
# Let TWRP publish ro.crypto.state/type when it detects /data FBE.
|
||||
# Stock teei_daemon begins polling before ro.crypto.type=file appears; Beanpod
|
||||
|
|
@ -33,7 +32,6 @@ PRODUCT_COPY_FILES += \
|
|||
$(DEVICE_PATH)/recovery/root/init.recovery.mt6835.rc:$(TARGET_COPY_OUT_RECOVERY)/root/init.recovery.mt6835.rc \
|
||||
$(DEVICE_PATH)/recovery/root/init.recovery.mt8755.rc:$(TARGET_COPY_OUT_RECOVERY)/root/init.recovery.mt8755.rc \
|
||||
$(DEVICE_PATH)/recovery/root/init.recovery.crypto.rc:$(TARGET_COPY_OUT_RECOVERY)/root/init.recovery.crypto.rc \
|
||||
$(DEVICE_PATH)/recovery/root/system/etc/init/zz_sycamore_fscryptd.rc:$(TARGET_COPY_OUT_RECOVERY)/root/system/etc/init/zz_sycamore_fscryptd.rc \
|
||||
$(DEVICE_PATH)/recovery/root/system/etc/vintf/manifest.xml:$(TARGET_COPY_OUT_RECOVERY)/root/system/etc/vintf/manifest.xml \
|
||||
$(DEVICE_PATH)/recovery/root/system/etc/vintf/manifest/android.hardware.health-service.example.xml:$(TARGET_COPY_OUT_RECOVERY)/root/system/etc/vintf/manifest/android.hardware.health-service.example.xml \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/manifest.xml:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/manifest.xml \
|
||||
|
|
@ -79,7 +77,6 @@ PRODUCT_PACKAGES += \
|
|||
sycamore_tee_imsg_log \
|
||||
sycamore_tee_vfs \
|
||||
sycamore_teei_daemon \
|
||||
libsycamore_keytrace
|
||||
|
||||
PRODUCT_VENDOR_PROPERTIES += \
|
||||
ro.vendor.mtk_ufs_support=1 \
|
||||
|
|
@ -94,3 +91,7 @@ PRODUCT_COPY_FILES += \
|
|||
|
||||
PRODUCT_COPY_FILES += \
|
||||
$(LOCAL_PATH)/recovery/root/system/etc/init/zz_sycamore_hwservicemanager.rc:$(TARGET_COPY_OUT_RECOVERY)/root/system/etc/init/zz_sycamore_hwservicemanager.rc
|
||||
|
||||
# Device-side Keystore2 database staging for Android 16 FBE.
|
||||
PRODUCT_COPY_FILES += \
|
||||
$(DEVICE_PATH)/recovery/root/system/bin/sycamore_keystore2_stage.sh:$(TARGET_COPY_OUT_RECOVERY)/root/system/bin/sycamore_keystore2_stage.sh
|
||||
|
|
|
|||
|
|
@ -1,82 +0,0 @@
|
|||
DEVICE_PATH := device/motorola/sycamore_row_5G
|
||||
|
||||
PRODUCT_USE_DYNAMIC_PARTITIONS := true
|
||||
ENABLE_VIRTUAL_AB := true
|
||||
|
||||
# This is the exact list exposed by ro.product.ab_ota_partitions on the live build.
|
||||
AB_OTA_PARTITIONS := \
|
||||
init_boot \
|
||||
product \
|
||||
system \
|
||||
system_ext \
|
||||
vendor
|
||||
|
||||
PRODUCT_SOONG_NAMESPACES += $(DEVICE_PATH)
|
||||
|
||||
# V16 boot-decrypt-unlock: expose the real FBE mode before teei_daemon starts.
|
||||
# The stock daemon snapshots these read-only properties in its startup thread;
|
||||
# setting them later from TWRP's partition scan leaves that thread waiting on
|
||||
# the legacy vold.decrypt fallback instead of issuing the FBE unlock ioctl.
|
||||
PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
|
||||
ro.product.device=XT2575-4 \
|
||||
ro.crypto.state=encrypted \
|
||||
ro.crypto.type=file
|
||||
|
||||
PRODUCT_COPY_FILES += \
|
||||
$(DEVICE_PATH)/recovery.fstab:$(TARGET_COPY_OUT_RECOVERY)/root/system/etc/recovery.fstab \
|
||||
$(DEVICE_PATH)/recovery/root/init.recovery.mt6835.rc:$(TARGET_COPY_OUT_RECOVERY)/root/init.recovery.mt6835.rc \
|
||||
$(DEVICE_PATH)/recovery/root/init.recovery.mt8755.rc:$(TARGET_COPY_OUT_RECOVERY)/root/init.recovery.mt8755.rc \
|
||||
$(DEVICE_PATH)/recovery/root/init.recovery.crypto.rc:$(TARGET_COPY_OUT_RECOVERY)/root/init.recovery.crypto.rc \
|
||||
$(DEVICE_PATH)/recovery/root/system/etc/vintf/manifest.xml:$(TARGET_COPY_OUT_RECOVERY)/root/system/etc/vintf/manifest.xml \
|
||||
$(DEVICE_PATH)/recovery/root/system/etc/vintf/manifest/android.hardware.health-service.example.xml:$(TARGET_COPY_OUT_RECOVERY)/root/system/etc/vintf/manifest/android.hardware.health-service.example.xml \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/manifest.xml:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/manifest.xml \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/etc/vintf/manifest/android.hardware.health-service.example.xml:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/etc/vintf/manifest/android.hardware.health-service.example.xml \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/thh/ta/0102030405060708090a0b0c0d0e0f10.ta:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/thh/ta/0102030405060708090a0b0c0d0e0f10.ta \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/thh/ta/020f0000000000000000000000000000.ta:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/thh/ta/020f0000000000000000000000000000.ta \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/thh/ta/06090000000000000000000000000000.ta:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/thh/ta/06090000000000000000000000000000.ta \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/thh/ta/08030000000000000000000000000000.ta:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/thh/ta/08030000000000000000000000000000.ta \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/thh/ta/08110000000000000000000000000000.ta:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/thh/ta/08110000000000000000000000000000.ta \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/thh/ta/40188311faf343488db888ad39496f9a.ta:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/thh/ta/40188311faf343488db888ad39496f9a.ta \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/thh/ta/5020170115e016302017012521300000.ta:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/thh/ta/5020170115e016302017012521300000.ta \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/thh/ta/5f7a5b3b29b041bca249524a031a00e3.ta:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/thh/ta/5f7a5b3b29b041bca249524a031a00e3.ta \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/thh/ta/8888c04fc30c4dd0a319ea29643d4d4c.ta:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/thh/ta/8888c04fc30c4dd0a319ea29643d4d4c.ta \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/thh/ta/abcd270ea5c44c58bcd3384a2fa2539e.ta:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/thh/ta/abcd270ea5c44c58bcd3384a2fa2539e.ta \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/thh/ta/c09c9c5daa504b78b0e46eda61556c3a.ta:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/thh/ta/c09c9c5daa504b78b0e46eda61556c3a.ta \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/thh/ta/c1882f2d885e4e13a8c8e2622461b2fa.ta:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/thh/ta/c1882f2d885e4e13a8c8e2622461b2fa.ta \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/thh/ta/d91f322ad5a441d5955110eda3272fc0.ta:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/thh/ta/d91f322ad5a441d5955110eda3272fc0.ta \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/thh/ta/e97c270ea5c44c58bcd3384a2fa2539e.ta:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/thh/ta/e97c270ea5c44c58bcd3384a2fa2539e.ta \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/thh/ta/isee_model.json:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/thh/ta/isee_model.json \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/etc/vintf/manifest/android.hardware.security.keymint-service.beanpod.xml:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/etc/vintf/manifest/android.hardware.security.keymint-service.beanpod.xml \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/etc/vintf/manifest/android.hardware.security.secureclock-service.beanpod.xml:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/etc/vintf/manifest/android.hardware.security.secureclock-service.beanpod.xml \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/etc/vintf/manifest/android.hardware.security.sharedsecret-service.beanpod.xml:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/etc/vintf/manifest/android.hardware.security.sharedsecret-service.beanpod.xml \
|
||||
$(DEVICE_PATH)/recovery/root/vendor/etc/vintf/manifest/android.hardware.gatekeeper@1.0-service.xml:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/etc/vintf/manifest/android.hardware.gatekeeper@1.0-service.xml
|
||||
|
||||
PRODUCT_PACKAGES += \
|
||||
sycamore_gatekeeper_impl \
|
||||
sycamore_gatekeeper_hidl \
|
||||
sycamore_gatekeeper_service \
|
||||
sycamore_gatekeeper_soft \
|
||||
sycamore_gatekeeper_tee \
|
||||
sycamore_keymint_ndk_v2 \
|
||||
sycamore_keymint_private_utils \
|
||||
sycamore_keymaster_messages \
|
||||
sycamore_keymaster_portable \
|
||||
sycamore_keymint_private \
|
||||
sycamore_puresoft_keymaster \
|
||||
sycamore_soft_attestation \
|
||||
sycamore_cppbor_external \
|
||||
sycamore_cppcose_rkp \
|
||||
sycamore_keymint_service \
|
||||
sycamore_secureclock_ndk_v1 \
|
||||
sycamore_sharedsecret_ndk_v1 \
|
||||
sycamore_tee_common \
|
||||
sycamore_tee_imsg_log \
|
||||
sycamore_tee_vfs \
|
||||
sycamore_teei_daemon \
|
||||
libsycamore_keytrace
|
||||
|
||||
PRODUCT_VENDOR_PROPERTIES += \
|
||||
ro.vendor.mtk_ufs_support=1 \
|
||||
ro.vendor.mtk_boot_devices=soc/112b0000.ufshci \
|
||||
ro.hardware.gatekeeper=beanpod \
|
||||
ro.crypto.volume.filenames_mode=aes-256-cts
|
||||
|
|
@ -1,298 +0,0 @@
|
|||
// Diagnostic-only Beanpod STORAGE_KEY boundary tracer.
|
||||
// Logs only length and SHA-256, then calls the stock A16 implementation.
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <dlfcn.h>
|
||||
#include <string>
|
||||
|
||||
#include <android/log.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr const char* kSetKeyMaterialSymbol =
|
||||
"_ZN9keymaster16ExportKeyRequest14SetKeyMaterialEPKvm";
|
||||
constexpr const char* kGetPropertySymbol =
|
||||
"_ZN7android4base11GetPropertyERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEES9_";
|
||||
|
||||
// Microtrust uses the GlobalPlatform client ABI, but its headers are not
|
||||
// shipped in this recovery tree. These declarations contain only the stable
|
||||
// ABI prefix needed to inspect the four operation parameters. The 24-byte
|
||||
// parameter union and 112-byte operation layout are also verified against the
|
||||
// exact stock libTEECommon.so used by Beanpod.
|
||||
struct TEEC_Context;
|
||||
struct TEEC_Session;
|
||||
|
||||
struct TEEC_SharedMemory {
|
||||
void* buffer;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct TEEC_TempMemoryReference {
|
||||
void* buffer;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct TEEC_RegisteredMemoryReference {
|
||||
TEEC_SharedMemory* parent;
|
||||
size_t size;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
union TEEC_Parameter {
|
||||
TEEC_TempMemoryReference tmpref;
|
||||
TEEC_RegisteredMemoryReference memref;
|
||||
uint8_t abi_size[24];
|
||||
};
|
||||
|
||||
struct TEEC_Operation {
|
||||
uint32_t started;
|
||||
uint32_t paramTypes;
|
||||
TEEC_Parameter params[4];
|
||||
void* session;
|
||||
};
|
||||
|
||||
static_assert(sizeof(TEEC_Parameter) == 24);
|
||||
static_assert(sizeof(TEEC_Operation) == 112);
|
||||
|
||||
using TEEC_Result = uint32_t;
|
||||
using InvokeCommand = TEEC_Result (*)(TEEC_Session*, uint32_t, TEEC_Operation*, uint32_t*);
|
||||
|
||||
constexpr uint32_t kTeecSuccess = 0;
|
||||
constexpr uint32_t kTempInput = 0x5;
|
||||
constexpr uint32_t kTempOutput = 0x6;
|
||||
constexpr uint32_t kTempInout = 0x7;
|
||||
constexpr uint32_t kWhole = 0xc;
|
||||
constexpr uint32_t kPartialInput = 0xd;
|
||||
constexpr uint32_t kPartialOutput = 0xe;
|
||||
constexpr uint32_t kPartialInout = 0xf;
|
||||
|
||||
struct ByteRange {
|
||||
const uint8_t* data = nullptr;
|
||||
size_t size = 0;
|
||||
bool found = false;
|
||||
};
|
||||
|
||||
uint32_t ParamType(const TEEC_Operation* operation, size_t index) {
|
||||
return (operation->paramTypes >> (index * 4)) & 0xf;
|
||||
}
|
||||
|
||||
ByteRange FindInput(const TEEC_Operation* operation) {
|
||||
if (operation == nullptr) return {};
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
const uint32_t type = ParamType(operation, i);
|
||||
if (type == kTempInput || type == kTempInout) {
|
||||
const auto& ref = operation->params[i].tmpref;
|
||||
return {static_cast<const uint8_t*>(ref.buffer), ref.size, true};
|
||||
}
|
||||
if (type == kWhole || type == kPartialInput || type == kPartialInout) {
|
||||
const auto& ref = operation->params[i].memref;
|
||||
if (ref.parent == nullptr) return {};
|
||||
const size_t offset = type == kWhole ? 0 : ref.offset;
|
||||
const size_t size = type == kWhole ? ref.parent->size : ref.size;
|
||||
return {static_cast<const uint8_t*>(ref.parent->buffer) + offset, size, true};
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
ByteRange FindOutput(const TEEC_Operation* operation) {
|
||||
if (operation == nullptr) return {};
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
const uint32_t type = ParamType(operation, i);
|
||||
if (type == kTempOutput || type == kTempInout) {
|
||||
const auto& ref = operation->params[i].tmpref;
|
||||
return {static_cast<const uint8_t*>(ref.buffer), ref.size, true};
|
||||
}
|
||||
if (type == kWhole || type == kPartialOutput || type == kPartialInout) {
|
||||
const auto& ref = operation->params[i].memref;
|
||||
if (ref.parent == nullptr) return {};
|
||||
const size_t offset = type == kWhole ? 0 : ref.offset;
|
||||
const size_t size = type == kWhole ? ref.parent->size : ref.size;
|
||||
return {static_cast<const uint8_t*>(ref.parent->buffer) + offset, size, true};
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void DigestHex(const uint8_t* data, size_t size, char (&hex)[SHA256_DIGEST_LENGTH * 2 + 1]) {
|
||||
static constexpr uint8_t empty = 0;
|
||||
uint8_t digest[SHA256_DIGEST_LENGTH];
|
||||
SHA256(size == 0 ? &empty : data, size, digest);
|
||||
static constexpr char digits[] = "0123456789abcdef";
|
||||
for (size_t i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
|
||||
hex[i * 2] = digits[digest[i] >> 4];
|
||||
hex[i * 2 + 1] = digits[digest[i] & 0x0f];
|
||||
}
|
||||
hex[sizeof(hex) - 1] = '\0';
|
||||
}
|
||||
|
||||
bool HasKeymasterError(uint32_t command) {
|
||||
switch (command) {
|
||||
case 0x04:
|
||||
case 0x08:
|
||||
case 0x0c:
|
||||
case 0x18:
|
||||
case 0x48:
|
||||
case 0x4c:
|
||||
case 0x50:
|
||||
case 0x84:
|
||||
case 0x340000:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void LogDigest(const void* data, size_t size) {
|
||||
if (size != 64) return;
|
||||
|
||||
static std::atomic_flag logged = ATOMIC_FLAG_INIT;
|
||||
if (logged.test_and_set()) return;
|
||||
|
||||
uint8_t digest[SHA256_DIGEST_LENGTH];
|
||||
SHA256(static_cast<const uint8_t*>(data), size, digest);
|
||||
char hex[SHA256_DIGEST_LENGTH * 2 + 1];
|
||||
static constexpr char digits[] = "0123456789abcdef";
|
||||
for (size_t i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
|
||||
hex[i * 2] = digits[digest[i] >> 4];
|
||||
hex[i * 2 + 1] = digits[digest[i] & 0x0f];
|
||||
}
|
||||
hex[sizeof(hex) - 1] = '\0';
|
||||
__android_log_print(ANDROID_LOG_INFO, "SYCA_DEKEY",
|
||||
"SYCA_DEKEY_D len=%zu sha256=%s", size, hex);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Diagnostic V13: interpose the single GlobalPlatform boundary used by both
|
||||
// Beanpod request wrappers. This observes the registered-memory ranges but
|
||||
// never writes to the operation, shared memory, result, or return-origin.
|
||||
extern "C" TEEC_Result TEEC_InvokeCommand(TEEC_Session* session, uint32_t command,
|
||||
TEEC_Operation* operation, uint32_t* return_origin) {
|
||||
static const InvokeCommand original =
|
||||
reinterpret_cast<InvokeCommand>(dlsym(RTLD_NEXT, "TEEC_InvokeCommand"));
|
||||
if (original == nullptr) {
|
||||
__android_log_print(ANDROID_LOG_FATAL, "SYCA_TA_TRACE",
|
||||
"stock TEEC_InvokeCommand symbol unavailable");
|
||||
__builtin_trap();
|
||||
}
|
||||
|
||||
static std::atomic<uint64_t> next_sequence{0};
|
||||
const uint64_t sequence = next_sequence.fetch_add(1, std::memory_order_relaxed) + 1;
|
||||
const ByteRange input = FindInput(operation);
|
||||
const ByteRange output_before = FindOutput(operation);
|
||||
const uint8_t* input_data = input.found ? input.data : nullptr;
|
||||
const size_t input_size = input.found ? input.size : 0;
|
||||
char input_hash[SHA256_DIGEST_LENGTH * 2 + 1];
|
||||
DigestHex(input_data, input_size, input_hash);
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "SYCA_TA_TRACE",
|
||||
"SYCA_TA_SEQ=%llu session=0x%llx cmd=0x%x in_len=%zu "
|
||||
"in_sha256=%s out_capacity=%zu",
|
||||
static_cast<unsigned long long>(sequence),
|
||||
static_cast<unsigned long long>(reinterpret_cast<uintptr_t>(session)),
|
||||
command, input_size, input_hash,
|
||||
output_before.found ? output_before.size : 0);
|
||||
|
||||
const TEEC_Result result = original(session, command, operation, return_origin);
|
||||
|
||||
const ByteRange output_after = FindOutput(operation);
|
||||
// A failed TEEC transport did not return a serialized TA response. The
|
||||
// memref can still retain its pre-call capacity, which must not be logged
|
||||
// or hashed as though it were returned data.
|
||||
const bool has_response = result == kTeecSuccess && output_after.found;
|
||||
const uint8_t* output_data = has_response ? output_after.data : nullptr;
|
||||
const size_t output_size = has_response ? output_after.size : 0;
|
||||
char output_hash[SHA256_DIGEST_LENGTH * 2 + 1];
|
||||
DigestHex(output_data, output_size, output_hash);
|
||||
char origin[16];
|
||||
if (return_origin == nullptr) {
|
||||
memcpy(origin, "NA", 3);
|
||||
} else {
|
||||
snprintf(origin, sizeof(origin), "%u", *return_origin);
|
||||
}
|
||||
|
||||
if (result == kTeecSuccess && HasKeymasterError(command) && output_size >= sizeof(int32_t)) {
|
||||
int32_t keymaster_error;
|
||||
memcpy(&keymaster_error, output_data, sizeof(keymaster_error));
|
||||
__android_log_print(ANDROID_LOG_INFO, "SYCA_TA_TRACE",
|
||||
"SYCA_TA_RET_SEQ=%llu cmd=0x%x teec_ret=%u origin=%s out_len=%zu "
|
||||
"out_sha256=%s km_error=%d",
|
||||
static_cast<unsigned long long>(sequence), command, result, origin,
|
||||
output_size, output_hash, keymaster_error);
|
||||
} else {
|
||||
__android_log_print(ANDROID_LOG_INFO, "SYCA_TA_TRACE",
|
||||
"SYCA_TA_RET_SEQ=%llu cmd=0x%x teec_ret=%u origin=%s out_len=%zu "
|
||||
"out_sha256=%s",
|
||||
static_cast<unsigned long long>(sequence), command, result, origin,
|
||||
output_size, output_hash);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace android::base {
|
||||
|
||||
// V10-IDENTITY one-variable experiment. Beanpod obtains these two fields
|
||||
// through android::base::GetProperty() while constructing BPConfigureRequest
|
||||
// for command 0x48. Override only these Beanpod-facing lookups and delegate
|
||||
// every other property unchanged.
|
||||
std::string GetProperty(const std::string& key, const std::string& default_value) {
|
||||
if (key == "ro.product.name" || key == "ro.product.device") {
|
||||
constexpr const char* kStockIdentity = "XT2575-4";
|
||||
__android_log_print(ANDROID_LOG_INFO, "SYCA_IDENTITY",
|
||||
"%s=%s", key.c_str(), kStockIdentity);
|
||||
return kStockIdentity;
|
||||
}
|
||||
|
||||
using Original = std::string (*)(const std::string&, const std::string&);
|
||||
static const Original original =
|
||||
reinterpret_cast<Original>(dlsym(RTLD_NEXT, kGetPropertySymbol));
|
||||
if (original == nullptr) {
|
||||
__android_log_print(ANDROID_LOG_FATAL, "SYCA_IDENTITY",
|
||||
"stock GetProperty symbol unavailable");
|
||||
__builtin_trap();
|
||||
}
|
||||
return original(key, default_value);
|
||||
}
|
||||
|
||||
} // namespace android::base
|
||||
|
||||
namespace keymaster {
|
||||
|
||||
// V9-OSVERSION one-variable experiment. Beanpod dynamically imports this
|
||||
// helper when building BPConfigureRequest for command 0x48. Keep recovery's
|
||||
// global Android 12 properties intact and change only the value observed by
|
||||
// this Beanpod process.
|
||||
uint32_t GetOsVersion() {
|
||||
constexpr uint32_t kAndroid16OsVersion = 160000;
|
||||
__android_log_print(ANDROID_LOG_INFO, "SYCA_OSVERSION",
|
||||
"Beanpod ConfigDeviceInfo os_version=%u",
|
||||
kAndroid16OsVersion);
|
||||
return kAndroid16OsVersion;
|
||||
}
|
||||
|
||||
class ExportKeyRequest {
|
||||
public:
|
||||
void SetKeyMaterial(const void* key_material, size_t length);
|
||||
};
|
||||
|
||||
void ExportKeyRequest::SetKeyMaterial(const void* key_material, size_t length) {
|
||||
using Original = void (*)(ExportKeyRequest*, const void*, size_t);
|
||||
static const Original original = reinterpret_cast<Original>(
|
||||
dlsym(RTLD_NEXT, kSetKeyMaterialSymbol));
|
||||
|
||||
LogDigest(key_material, length);
|
||||
if (original == nullptr) {
|
||||
__android_log_print(ANDROID_LOG_FATAL, "SYCA_DEKEY",
|
||||
"stock SetKeyMaterial symbol unavailable");
|
||||
__builtin_trap();
|
||||
}
|
||||
original(this, key_material, length);
|
||||
}
|
||||
|
||||
} // namespace keymaster
|
||||
|
|
@ -1,222 +0,0 @@
|
|||
#include <android-base/logging.h>
|
||||
#include <errno.h>
|
||||
#include <linux/un.h>
|
||||
#include <signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "FsCrypt.h"
|
||||
#include "SycamoreFscryptIpc.h"
|
||||
|
||||
namespace sycamore = android::vold::sycamore;
|
||||
|
||||
namespace {
|
||||
|
||||
bool ReadFully(int fd, void* data, size_t size) {
|
||||
auto* p = static_cast<uint8_t*>(data);
|
||||
while (size != 0) {
|
||||
ssize_t n = TEMP_FAILURE_RETRY(read(fd, p, size));
|
||||
if (n <= 0) return false;
|
||||
p += n;
|
||||
size -= n;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteFully(int fd, const void* data, size_t size) {
|
||||
const auto* p = static_cast<const uint8_t*>(data);
|
||||
while (size != 0) {
|
||||
ssize_t n = TEMP_FAILURE_RETRY(write(fd, p, size));
|
||||
if (n <= 0) return false;
|
||||
p += n;
|
||||
size -= n;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool Consume(const std::vector<uint8_t>& payload, size_t* offset, T* value) {
|
||||
if (*offset > payload.size() || sizeof(T) > payload.size() - *offset) return false;
|
||||
memcpy(value, payload.data() + *offset, sizeof(T));
|
||||
*offset += sizeof(T);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Append(std::vector<uint8_t>* payload, const T& value) {
|
||||
const auto* p = reinterpret_cast<const uint8_t*>(&value);
|
||||
payload->insert(payload->end(), p, p + sizeof(value));
|
||||
}
|
||||
|
||||
bool IsRecoveryPeer(int fd) {
|
||||
ucred cred = {};
|
||||
socklen_t cred_len = sizeof(cred);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len) == -1 || cred.uid != 0) {
|
||||
return false;
|
||||
}
|
||||
char context[128] = {};
|
||||
socklen_t context_len = sizeof(context);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_PEERSEC, context, &context_len) == -1) return false;
|
||||
return std::string(context, strnlen(context, context_len)) == "u:r:recovery:s0";
|
||||
}
|
||||
|
||||
int32_t Dispatch(sycamore::Command command, std::vector<uint8_t>* request,
|
||||
std::vector<uint8_t>* response) {
|
||||
size_t offset = 0;
|
||||
switch (command) {
|
||||
case sycamore::Command::kPing:
|
||||
return request->empty() ? 0 : -EINVAL;
|
||||
case sycamore::Command::kInitSystemwide:
|
||||
if (!request->empty()) return -EINVAL;
|
||||
LOG(INFO) << "sycamore_fscryptd: INIT_SYSTEMWIDE begin";
|
||||
if (!fscrypt_initialize_systemwide_keys()) {
|
||||
LOG(ERROR) << "sycamore_fscryptd: INIT_SYSTEMWIDE fail";
|
||||
return -EIO;
|
||||
}
|
||||
LOG(INFO) << "sycamore_fscryptd: INIT_SYSTEMWIDE success";
|
||||
return 0;
|
||||
case sycamore::Command::kInitUser0:
|
||||
if (!request->empty()) return -EINVAL;
|
||||
LOG(INFO) << "sycamore_fscryptd: INIT_USER0 begin";
|
||||
if (!fscrypt_init_user0()) {
|
||||
LOG(ERROR) << "sycamore_fscryptd: INIT_USER0 fail";
|
||||
return -EIO;
|
||||
}
|
||||
LOG(INFO) << "sycamore_fscryptd: INIT_USER0 success";
|
||||
return 0;
|
||||
case sycamore::Command::kUnlockUser: {
|
||||
int32_t user_id;
|
||||
int32_t serial;
|
||||
uint32_t secret_size;
|
||||
if (!Consume(*request, &offset, &user_id) || !Consume(*request, &offset, &serial) ||
|
||||
!Consume(*request, &offset, &secret_size) || user_id < 0 || user_id > 9999 ||
|
||||
secret_size > 1024 || secret_size != request->size() - offset) {
|
||||
return -EINVAL;
|
||||
}
|
||||
std::string secret(reinterpret_cast<const char*>(request->data() + offset), secret_size);
|
||||
LOG(INFO) << "sycamore_fscryptd: UNLOCK_USER user=" << user_id << " begin";
|
||||
bool ok = fscrypt_unlock_user_key(user_id, serial, secret);
|
||||
std::fill(secret.begin(), secret.end(), '\0');
|
||||
std::fill(request->begin(), request->end(), 0);
|
||||
if (ok) {
|
||||
LOG(INFO) << "sycamore_fscryptd: UNLOCK_USER user=" << user_id << " success";
|
||||
} else {
|
||||
LOG(ERROR) << "sycamore_fscryptd: UNLOCK_USER user=" << user_id << " fail";
|
||||
}
|
||||
return ok ? 0 : -EIO;
|
||||
}
|
||||
case sycamore::Command::kPrepareUserStorage: {
|
||||
int32_t user_id;
|
||||
int32_t serial;
|
||||
int32_t flags;
|
||||
uint32_t uuid_size;
|
||||
if (!Consume(*request, &offset, &user_id) || !Consume(*request, &offset, &serial) ||
|
||||
!Consume(*request, &offset, &flags) || !Consume(*request, &offset, &uuid_size) ||
|
||||
user_id < 0 || user_id > 9999 || uuid_size > 128 ||
|
||||
uuid_size != request->size() - offset || (flags & ~3) != 0 || flags == 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
std::string uuid(reinterpret_cast<const char*>(request->data() + offset), uuid_size);
|
||||
return fscrypt_prepare_user_storage(uuid, user_id, serial, flags) ? 0 : -EIO;
|
||||
}
|
||||
case sycamore::Command::kClassifyPolicy: {
|
||||
uint32_t ref_size;
|
||||
if (!Consume(*request, &offset, &ref_size) || ref_size == 0 || ref_size > 64 ||
|
||||
ref_size != request->size() - offset) {
|
||||
return -EINVAL;
|
||||
}
|
||||
std::string ref(reinterpret_cast<const char*>(request->data() + offset), ref_size);
|
||||
FscryptPolicyKind kind = FscryptPolicyKind::kUnknown;
|
||||
userid_t user_id = 0;
|
||||
if (!fscrypt_classify_policy_ref(ref, &kind, &user_id)) return -ENOENT;
|
||||
int32_t kind_value = static_cast<int32_t>(kind);
|
||||
int32_t uid = user_id;
|
||||
Append(response, kind_value);
|
||||
Append(response, uid);
|
||||
return 0;
|
||||
}
|
||||
case sycamore::Command::kResolvePolicy: {
|
||||
int32_t kind_value;
|
||||
int32_t user_id;
|
||||
if (!Consume(*request, &offset, &kind_value) || !Consume(*request, &offset, &user_id) ||
|
||||
offset != request->size() || user_id < 0 || user_id > 9999) {
|
||||
return -EINVAL;
|
||||
}
|
||||
std::string ref;
|
||||
if (!fscrypt_resolve_policy_ref(static_cast<FscryptPolicyKind>(kind_value), user_id,
|
||||
&ref) ||
|
||||
ref.empty() || ref.size() > 64) {
|
||||
return -ENOENT;
|
||||
}
|
||||
response->assign(ref.begin(), ref.end());
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
void HandleClient(int fd) {
|
||||
if (!IsRecoveryPeer(fd)) {
|
||||
LOG(ERROR) << "sycamore_fscryptd: rejected unauthorized peer";
|
||||
return;
|
||||
}
|
||||
sycamore::RequestHeader header = {};
|
||||
if (!ReadFully(fd, &header, sizeof(header)) || header.magic != sycamore::kMagic ||
|
||||
header.version != sycamore::kVersion || header.payload_size > sycamore::kMaxPayload) {
|
||||
return;
|
||||
}
|
||||
std::vector<uint8_t> request(header.payload_size);
|
||||
if (!request.empty() && !ReadFully(fd, request.data(), request.size())) return;
|
||||
std::vector<uint8_t> response;
|
||||
int32_t status = Dispatch(static_cast<sycamore::Command>(header.command), &request, &response);
|
||||
sycamore::ResponseHeader reply{sycamore::kMagic, sycamore::kVersion, header.command, status,
|
||||
static_cast<uint32_t>(response.size())};
|
||||
WriteFully(fd, &reply, sizeof(reply));
|
||||
if (!response.empty()) WriteFully(fd, response.data(), response.size());
|
||||
std::fill(request.begin(), request.end(), 0);
|
||||
}
|
||||
|
||||
int CreateServerSocket() {
|
||||
int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
if (fd == -1) return -1;
|
||||
sockaddr_un addr = {};
|
||||
addr.sun_family = AF_UNIX;
|
||||
static_assert(sizeof(sycamore::kSocketName) <= sizeof(addr.sun_path));
|
||||
memcpy(addr.sun_path + 1, sycamore::kSocketName, sizeof(sycamore::kSocketName) - 1);
|
||||
socklen_t len = offsetof(sockaddr_un, sun_path) + 1 + sizeof(sycamore::kSocketName) - 1;
|
||||
if (bind(fd, reinterpret_cast<sockaddr*>(&addr), len) == -1 || listen(fd, 4) == -1) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main() {
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
int server = CreateServerSocket();
|
||||
if (server == -1) {
|
||||
PLOG(ERROR) << "sycamore_fscryptd: unable to create private socket";
|
||||
return 1;
|
||||
}
|
||||
LOG(INFO) << "sycamore_fscryptd: started";
|
||||
for (;;) {
|
||||
int client = TEMP_FAILURE_RETRY(accept4(server, nullptr, nullptr, SOCK_CLOEXEC));
|
||||
if (client == -1) {
|
||||
if (errno == EINTR) continue;
|
||||
PLOG(ERROR) << "sycamore_fscryptd: accept failed";
|
||||
return 1;
|
||||
}
|
||||
HandleClient(client);
|
||||
close(client);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue