Reach QTEE: credentials, client env and the app loader, with no QCBOR
fingerprintd's own code now talks to QTEE. On the phone:
root object on /dev/tee0
client env obtained (uid 0, 13-byte credentials)
QSEECOM-compat app loader (UID 122) opened
The credentials object is ours rather than libqcomtee's. Upstream's exists only
to build a thirteen-byte CBOR map and drags in QCBOR to do it, so
packaging/make-libqcomtee.sh compiles the two sources that matter and drops
credentials_obj.c entirely -- nothing else references it, and the library then
has no dependency beyond libc. The map is built in Fingerprintd:Tee where it is
pinned byte-for-byte against the string verified on-device, and the object's
two-op read protocol is served here.
Three interop details, all of which cost a build cycle:
* libqcomtee's headers carry no extern "C" guard, having only ever been
consumed from C, so everything came out C++-mangled. They also pull in
<stdatomic.h> and <stdio.h>, which under libc++ drag in templates that may
not appear inside extern "C" -- so those are included first.
* tee_call_t's second parameter is unsigned long on glibc and int on musl.
The native build is glibc and the phone is musl; both forms are compiled.
* On the callback path a UBUF_OUTPUT param arrives with addr = NULL. The
dispatcher supplies the buffer, so a handler POINTS the param at its own
storage rather than writing through the incoming address. Doing the latter
is a null dereference that takes the supplicant thread with it, which is
how the first run against real QTEE ended -- with the correct behaviour
already spelled out in the module comment above the code that ignored it.
That comment now says so in as many words.
This commit is contained in:
parent
93692c9505
commit
a91fb2ff58
6 changed files with 708 additions and 25 deletions
82
packaging/make-libqcomtee.sh
Executable file
82
packaging/make-libqcomtee.sh
Executable file
|
|
@ -0,0 +1,82 @@
|
|||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
# SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
|
||||
# make-libqcomtee.sh — build libqcomtee for a target, without QCBOR.
|
||||
#
|
||||
# packaging/make-libqcomtee.sh [--target=<triple> --sysroot=<dir>] [outdir]
|
||||
#
|
||||
# libqcomtee is Qualcomm's BSD-3 userspace client for QTEE (quic/quic-teec).
|
||||
# Upstream's CMake does find_package(QCBOR REQUIRED) and falls back to libcbor,
|
||||
# but that dependency exists for exactly one file, src/objects/credentials_obj.c,
|
||||
# which builds the {AttrUid, AttrSystemTime} CBOR map.
|
||||
#
|
||||
# fingerprintd builds that map itself in Fingerprintd:Tee, where it is thirteen
|
||||
# bytes under test rather than a library dependency, and implements the
|
||||
# credentials object's two-op read protocol in its own shell. So only two of
|
||||
# the three sources are needed:
|
||||
#
|
||||
# src/qcomtee_object.c the object/marshalling core
|
||||
# src/objects/mem_obj.c memory objects (CAPTURE_IMAGE needs a real region)
|
||||
#
|
||||
# Nothing in either references credentials_obj, so dropping it leaves the
|
||||
# library with no dependency beyond libc.
|
||||
set -eu
|
||||
|
||||
REPO="${QUIC_TEEC_REPO:-https://github.com/quic/quic-teec.git}"
|
||||
# Pinned. Upstream is small and moves rarely; an unpinned clone would change
|
||||
# the marshalling under us without notice.
|
||||
COMMIT="${QUIC_TEEC_COMMIT:-736419e}"
|
||||
SRC="${QUIC_TEEC_DIR:-$HOME/.cache/fingerprintd/quic-teec}"
|
||||
|
||||
TARGET=""
|
||||
SYSROOT=""
|
||||
MARCH=""
|
||||
OUT=""
|
||||
for a in "$@"; do
|
||||
case "$a" in
|
||||
--target=*) TARGET="${a#--target=}" ;;
|
||||
--sysroot=*) SYSROOT="${a#--sysroot=}" ;;
|
||||
--march=*) MARCH="${a#--march=}" ;;
|
||||
-*) echo "unknown option: $a" >&2; exit 1 ;;
|
||||
*) OUT="$a" ;;
|
||||
esac
|
||||
done
|
||||
[ -n "$OUT" ] || OUT="$HOME/.cache/fingerprintd/libqcomtee${TARGET:+-$TARGET}"
|
||||
|
||||
if [ ! -d "$SRC/.git" ]; then
|
||||
echo ">> cloning $REPO -> $SRC"
|
||||
mkdir -p "$(dirname "$SRC")"
|
||||
git clone -q "$REPO" "$SRC"
|
||||
git -C "$SRC" checkout -q "$COMMIT"
|
||||
elif [ -n "${QUIC_TEEC_DIR:-}" ]; then
|
||||
# A checkout the caller pointed us at is THEIRS. Never move its HEAD --
|
||||
# silently checking out a pin in someone's working tree is how you lose
|
||||
# uncommitted work. Report the mismatch and let them decide.
|
||||
have=$(git -C "$SRC" rev-parse --short HEAD)
|
||||
case "$COMMIT" in
|
||||
"$have"*) : ;;
|
||||
*) echo "!! $SRC is at $have, not the pinned $COMMIT." >&2
|
||||
echo "!! Building from it anyway; unset QUIC_TEEC_DIR to use a pinned clone." >&2 ;;
|
||||
esac
|
||||
else
|
||||
git -C "$SRC" fetch -q --all 2>/dev/null || true
|
||||
git -C "$SRC" checkout -q "$COMMIT"
|
||||
fi
|
||||
|
||||
mkdir -p "$OUT"
|
||||
set -- -O2 -Wall -fPIC
|
||||
[ -n "$TARGET" ] && set -- "$@" --target="$TARGET"
|
||||
[ -n "$SYSROOT" ] && set -- "$@" --sysroot="$SYSROOT"
|
||||
[ -n "$MARCH" ] && set -- "$@" -march="$MARCH"
|
||||
|
||||
echo ">> building libqcomtee.a (no QCBOR) for ${TARGET:-native}"
|
||||
for f in src/qcomtee_object.c src/objects/mem_obj.c; do
|
||||
clang "$@" -I"$SRC/libqcomtee/include" -I"$SRC/libqcomtee/src" \
|
||||
-c "$SRC/libqcomtee/$f" -o "$OUT/$(basename "$f" .c).o"
|
||||
done
|
||||
rm -f "$OUT/libqcomtee.a"
|
||||
llvm-ar rcs "$OUT/libqcomtee.a" "$OUT"/*.o
|
||||
mkdir -p "$OUT/include"
|
||||
cp "$SRC/libqcomtee/include/"*.h "$OUT/include/"
|
||||
|
||||
echo ">> done: $OUT/libqcomtee.a"
|
||||
Loading…
Reference in a new issue