Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
77d34e1
soc: apple: sep: preserve backing-store open errors
satchlj Oct 26, 2026
91c26b2
soc: apple: sep: refuse unreadable and partial identity records
satchlj Oct 26, 2026
ef4c427
soc: apple: sep: distinguish unreadable catacombs from missing ones
satchlj Oct 26, 2026
6b46c9f
soc: apple: sep: preserve the J613 26.6.2 existing-bag policy
satchlj Nov 3, 2026
b40f6bb
soc: apple: sep: expose passive selected-policy diagnostics
satchlj Nov 3, 2026
4a3e516
soc: apple: sep: update sensor host tests for diagnostic ABI 3
satchlj Nov 3, 2026
02eeffd
selftests: sep: include the read-only store error in the shim fixture
satchlj Nov 5, 2026
69a204d
Merge branch 'satchlj/port-234-20261104' into satchlj/port-345-20261104
satchlj Nov 5, 2026
90e4dea
Merge branch 'satchlj/port-234-20261104' into satchlj/port-345-20261104
satchlj Nov 5, 2026
3965338
ci: run the carried SEP identity-preservation regressions
satchlj Nov 5, 2026
a2dbf7e
ci: run the J613 selected-policy diagnostic regressions
satchlj Nov 5, 2026
3f525ea
Merge commit '33313096c66f4afdff4ef7060d20fe9bedebc34c' into satchlj/…
satchlj Nov 5, 2026
462f4a8
Merge commit '33313096c66f4afdff4ef7060d20fe9bedebc34c' into satchlj/…
satchlj Nov 5, 2026
0739bbc
Merge branch 'satchlj/port-234-20261104' into satchlj/port-345-20261104
satchlj Nov 5, 2026
9cd56e8
Merge commit 'b50066848322c6799c1433ee3a358aab2e9faabb' into satchlj/…
satchlj Nov 5, 2026
25c3f9c
Merge commit 'b50066848322c6799c1433ee3a358aab2e9faabb' into satchlj/…
satchlj Nov 5, 2026
2565987
Merge branch 'satchlj/port-234-20261104' into satchlj/port-345-20261104
satchlj Nov 5, 2026
a97cf43
Merge pull request #975 from aurora-silicon/satchlj/port-345-20261104
RyanTheTide Nov 10, 2026
cde6657
Merge branch 'integration/aurora' into satchlj/port-234-20261104
RyanTheTide Nov 10, 2026
4f5ecf6
tools/aurora-sep: tests: take the refkey ACL argument in the identity…
RyanTheTide Nov 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/workflows/sep-source.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,20 @@ jobs:
EOF
cc -Wall -Werror -Iinclude/uapi /tmp/sep-abi.c -o /tmp/sep-abi
/tmp/sep-abi
- name: Select the identity-test Rust toolchain
run: |
rustup toolchain install 1.85.0 --profile minimal --no-self-update
echo "RUSTUP_TOOLCHAIN=1.85.0" >> "$GITHUB_ENV"
- name: Test saved identity readers
run: |
python3 -m unittest tools/aurora-sep/tests/test_store_open_errors.py -v
python3 -O -m unittest tools/aurora-sep/tests/test_store_open_errors.py -v
python3 -m unittest tools/aurora-sep/tests/test_identity_preservation.py -v
python3 -O -m unittest tools/aurora-sep/tests/test_identity_preservation.py -v
- name: Test selected-policy diagnostics
run: |
python3 -m unittest tools/aurora-sep/tests/test_diag_policy.py tools/aurora-sep/tests/test_diag_sensor.py -v
python3 -O -m unittest tools/aurora-sep/tests/test_diag_policy.py tools/aurora-sep/tests/test_diag_sensor.py -v
- name: Test recovery utility and package sources
run: |
python3 -m unittest tools/aurora-sep/tests/test_sep_bio_identities.py -v
Expand Down
49 changes: 46 additions & 3 deletions Documentation/ABI/testing/sysfs-driver-apple-sep
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ Date: October 2026
KernelVersion: 7.1
Contact: Chris Kearney <chris@kearneymail.com>
Description:
(RO) Version of the diag interface: "2" for the attributes
(RO) Version of the diag interface: "3" for the attributes
and values described in this file. Version 2 added
sensor_attach and restore; version 1 had neither.
sensor_attach and restore; version 1 had neither. Version 3
adds the policy snapshot.

Within a version, attributes are only added, and an existing
attribute keeps its values and their meaning. A reader tests
Expand All @@ -19,7 +20,8 @@ Description:
bring-up got without reading the kernel log. It exists while
the driver is bound to the SEP: it is created at probe and
removed at unbind. Every attribute in it is read-only and
reads as one ASCII token followed by a newline.
reads as ASCII followed by a newline. The policy snapshot
contains space-separated key=value tokens.

Each value is the state the driver recorded when it made the
corresponding decision. Reading an attribute sends nothing
Expand All @@ -30,6 +32,26 @@ Description:
by the boot-time bring-up, so the sensor and touchid
attributes only move on once something has opened it.

This deployment uses the existing T8122 profile and v4
/dev/sep-bio interface. It does not add a new sensor protocol.
OS firmware and system firmware are separate: qualify both.

For an existing bag, select xart_writes=1, provision_keybag=0,
xart_guard=1 and xarm_trace=1. trusted_keys=0 and
filevault_api=0 omit the optional kernel APIs; both default
to 1 to preserve existing deployments. There is no boot_uuid
parameter: the OS identity comes from /chosen/apfs-preboot-uuid.
Writable J613 26.6.2 attachment rejects a missing DT identity,
explicit UUID override or disabled guard before opening xART.
Host-store or identity-index read failure refuses attachment.

Preserve the current keybag, host store, reference key, three
Catacombs, ownership journal and fprint records. Different
Linux roots must share the same current files globally, before
module load; the kernel opens them from init_task's root.
Never replace them with a snapshot or enrol again to migrate.
Readiness diagnostics do not prove a successful finger match.

What: /sys/bus/platform/devices/<unit>.sep/diag/profile
Date: October 2026
KernelVersion: 7.1
Expand Down Expand Up @@ -360,6 +382,27 @@ Description:
can only move from "unverified" to "blocked", once the guard
refuses a write.

What: /sys/bus/platform/devices/<unit>.sep/diag/policy
Date: November 2026
KernelVersion: 7.2
Contact: Satya Benson <satya@benson.earth>
Description:
(RO, ABI 3) A space-separated key=value snapshot of the
driver policy selected at probe: xart_writes (effective store
writability), provision_keybag, xart_guard (effective level),
trusted_keys, filevault_api, xarm_trace, refkey_v2 and
identity_override (0 or 1). API flags describe the selected
policy, not successful registration if that API later fails.

identity_source is pending before the driver selects it, dt
for /chosen/apfs-preboot-uuid, override for explicit parameters,
or missing. It is updated at the actual identity decision.
No UUID value, state, identity or key bytes are exposed.
Reads only use cached facts and never contact the enclave.
Module-parameter sysfs files need not exist; their absence
is not evidence of a mismatched policy. Older diagnostic
ABIs retain xart/xart_guard and kernel decision messages.

What: /sys/bus/platform/devices/<unit>.sep/diag/attach_ms
What: /sys/bus/platform/devices/<unit>.sep/diag/ready_ms
Date: November 2026
Expand Down
15 changes: 6 additions & 9 deletions drivers/soc/apple/bio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,22 +390,19 @@ impl IdentityIndex {
let Some(raw) = store.read(&identity_key())? else {
return Ok(index);
};
if raw.len() < 4 {
return Ok(index);
if raw.len() < 8 {
return Err(EINVAL);
}
if u32::from_le_bytes([raw[0], raw[1], raw[2], raw[3]]) != INDEX_FORMAT {
return Err(EINVAL);
}
if raw.len() < 8 {
return Ok(index);
}
let count = u32::from_le_bytes([raw[4], raw[5], raw[6], raw[7]]) as usize;
let stride = UUID_LEN + LABEL_LEN;
for i in 0..count.min(MAX_IDENTITIES) {
if count > MAX_IDENTITIES || raw.len() != 8 + count * stride {
return Err(EINVAL);
}
for i in 0..count {
let at = 8 + i * stride;
if at + stride > raw.len() {
break;
}
let mut entry = Identity::ZERO;
entry.uuid.copy_from_slice(&raw[at..at + UUID_LEN]);
entry
Expand Down
43 changes: 30 additions & 13 deletions drivers/soc/apple/catacomb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,28 +64,45 @@ pub(crate) fn write(kind: u8, blob: &[u8]) -> Result<()> {
file.sync()
}

pub(crate) fn read(kind: u8) -> Option<KVec<u8>> {
let path = path_for(kind)?;
let file = shim::StoreFile::open_readonly(path).ok()?;
let size = file.size().ok()?;
/// `Ok(None)` only when the file is missing. A file that exists but cannot be
/// read or fails validation is an error: "cannot tell" must never read as
/// "nothing saved", or a caller may select a fresh context over a saved one.
pub(crate) fn read(kind: u8) -> Result<Option<KVec<u8>>> {
let path = path_for(kind).ok_or(EINVAL)?;
let file = match shim::StoreFile::open_readonly(path) {
Ok(file) => file,
Err(e) if e == ENOENT => return Ok(None),
Err(e) => return Err(e),
};
let size = file.size()?;
if size < HEADER as u64 {
return None;
return Err(EINVAL);
}
let mut head = [0u8; HEADER];
file.read_exact(0, &mut head).ok()?;
file.read_exact(0, &mut head)?;
if head[..MAGIC.len()] != MAGIC {
return None;
return Err(EINVAL);
}
let len = u32::from_le_bytes([head[8], head[9], head[10], head[11]]) as usize;
let crc = u16::from_le_bytes([head[12], head[13]]);
if len == 0 || len > MAX_CATACOMB || size != (HEADER + len) as u64 {
return None;
return Err(EINVAL);
}
let mut blob: KVec<u8> = KVec::with_capacity(len, GFP_KERNEL).ok()?;
blob.resize(len, 0, GFP_KERNEL).ok()?;
file.read_exact(HEADER as u64, &mut blob).ok()?;
let mut blob: KVec<u8> = KVec::with_capacity(len, GFP_KERNEL)?;
blob.resize(len, 0, GFP_KERNEL)?;
file.read_exact(HEADER as u64, &mut blob)?;
if crc16_ccitt_false(&blob) != crc {
return None;
return Err(EINVAL);
}
Some(blob)
Ok(Some(blob))
}

/// True only for a present, valid file.
pub(crate) fn is_saved(kind: u8) -> bool {
matches!(read(kind), Ok(Some(_)))
}

/// True only when the file is provably missing.
pub(crate) fn is_absent(kind: u8) -> bool {
matches!(read(kind), Ok(None))
}
44 changes: 44 additions & 0 deletions drivers/soc/apple/diag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ extern "C" {
sepos13: bool,
xart: bool,
) -> c_int;
fn sep_diag_set_policy(
provision_keybag: bool,
trusted_keys: bool,
filevault_api: bool,
xarm_trace: bool,
refkey_v2: bool,
identity_override: bool,
);
fn sep_diag_set_identity_source(source: c_uint);
fn sep_diag_set_attach(attached: bool);
fn sep_diag_set_endpoints(count: c_uint);
fn sep_diag_set_keystore_open();
Expand Down Expand Up @@ -84,6 +93,28 @@ pub(crate) enum Restore {
Unproven = 3,
}

/// Boot-time policy, without identity values or key material.
pub(crate) struct Policy {
pub provision_keybag: bool,
pub trusted_keys: bool,
pub filevault_api: bool,
pub xarm_trace: bool,
pub refkey_v2: bool,
pub identity_override: bool,
}

/// The source selected by prepare_os_uuid, not the UUID itself.
pub(crate) enum IdentitySource {
DeviceTree = 1,
Override = 2,
Missing = 3,
}

pub(crate) fn identity_source(source: IdentitySource) {
// SAFETY: this only stores the source enum in the passive cache.
unsafe { sep_diag_set_identity_source(source as c_uint) };
}

/// Adds the `diag` group to the SEP device, with the facts fixed at probe. The
/// group goes away when the driver unbinds.
///
Expand All @@ -94,6 +125,7 @@ pub(crate) fn register(
profile: &profile::PlatformProfile,
xart_writable: bool,
guard: Option<(u8, bool)>,
policy: Policy,
) -> Result {
// Exhaustive, so a new bootstrap or key store fails to build here until
// the ABI has a value for it.
Expand All @@ -115,6 +147,18 @@ pub(crate) fn register(
// SAFETY: no preconditions; stores three words.
unsafe { sep_diag_set_xart_guard(c_uint::from(level), list_loaded, matching() as c_int) };

// SAFETY: the facts are fixed before the attribute group is published.
unsafe {
sep_diag_set_policy(
policy.provision_keybag,
policy.trusted_keys,
policy.filevault_api,
policy.xarm_trace,
policy.refkey_v2,
policy.identity_override,
)
};

// SAFETY: `dev` is bound for the duration of the call, which is what devres
// needs. `profile.name` is a `str`, valid for reads of `profile.name.len()`
// bytes; the shim copies at most that many, needs no NUL terminator, and
Expand Down
58 changes: 57 additions & 1 deletion drivers/soc/apple/diag_shim.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#include "shim.h"

/* The contract version; see Documentation/ABI/testing/sysfs-driver-apple-sep. */
#define SEP_DIAG_ABI 2
#define SEP_DIAG_ABI 3

#define SEP_DIAG_ATTACH_PENDING 0
#define SEP_DIAG_ATTACH_ATTACHED 1
Expand Down Expand Up @@ -71,6 +71,13 @@ static struct {
bool cold;
bool sepos13;
bool xart;
bool provision_keybag;
bool trusted_keys;
bool filevault_api;
bool xarm_trace;
bool refkey_v2;
bool identity_override;
atomic_t identity_source;
/* The xART guard's effective level (0: none runs), and its list. */
unsigned int xart_guard;
bool xart_guard_list;
Expand Down Expand Up @@ -147,6 +154,54 @@ static ssize_t xart_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RO(xart);

/* Parameter policy is captured at probe; the identity choice is cached later. */
static ssize_t policy_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
const char *identity;

switch (atomic_read(&sep_diag.identity_source)) {
case 1:
identity = "dt";
break;
case 2:
identity = "override";
break;
case 3:
identity = "missing";
break;
default:
identity = "pending";
break;
}
return sysfs_emit(buf,
"xart_writes=%u provision_keybag=%u xart_guard=%u "
"trusted_keys=%u filevault_api=%u xarm_trace=%u "
"refkey_v2=%u identity_override=%u identity_source=%s\n",
sep_diag.xart, sep_diag.provision_keybag, sep_diag.xart_guard,
sep_diag.trusted_keys, sep_diag.filevault_api, sep_diag.xarm_trace,
sep_diag.refkey_v2, sep_diag.identity_override, identity);
}
static DEVICE_ATTR_RO(policy);

void sep_diag_set_policy(bool provision_keybag, bool trusted_keys,
bool filevault_api, bool xarm_trace, bool refkey_v2,
bool identity_override)
{
sep_diag.provision_keybag = provision_keybag;
sep_diag.trusted_keys = trusted_keys;
sep_diag.filevault_api = filevault_api;
sep_diag.xarm_trace = xarm_trace;
sep_diag.refkey_v2 = refkey_v2;
sep_diag.identity_override = identity_override;
atomic_set(&sep_diag.identity_source, 0);
}

void sep_diag_set_identity_source(unsigned int source)
{
atomic_set(&sep_diag.identity_source, source);
}

static ssize_t attach_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
Expand Down Expand Up @@ -516,6 +571,7 @@ static struct attribute *sep_diag_attrs[] = {
&dev_attr_boot.attr,
&dev_attr_protocol.attr,
&dev_attr_xart.attr,
&dev_attr_policy.attr,
&dev_attr_attach.attr,
&dev_attr_endpoints.attr,
&dev_attr_keystore.attr,
Expand Down
9 changes: 9 additions & 0 deletions drivers/soc/apple/keybag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,15 @@ pub(crate) fn read(slot: Slot) -> Result<State> {
head[OFF_STATE + 3],
]);
if state == STATE_REFUSED {
let expected_crc = crc16_ccitt_false(&checksum_input(state, &[], &[0; UUID_LEN], &[])?);
let crc = u16::from_le_bytes([head[OFF_CRC], head[OFF_CRC + 1]]);
if size != HEADER as u64
|| crc != expected_crc
|| head[OFF_LEN..OFF_CRC].iter().any(|byte| *byte != 0)
|| head[OFF_CRC + 2..].iter().any(|byte| *byte != 0)
{
return Err(EINVAL);
}
return Ok(State::Absent(NoStoredKeyBag { slot }));
}
let Some(provenance) = UuidProvenance::from_state(state) else {
Expand Down
27 changes: 27 additions & 0 deletions drivers/soc/apple/profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -860,3 +860,30 @@ mod dart_window_tests {
}
}
}

/// The owner-qualified J613 OS-firmware lane; system firmware may differ.
pub(crate) fn j613_26_6_2() -> bool {
machine_has(b"apple,j613")
&& chosen_string(c"asahi,os-fw-version")
.as_deref()
.is_some_and(os_firmware_26_6_2)
}

fn os_firmware_26_6_2(raw: &[u8]) -> bool {
raw == b"26.6.2" || raw == b"26.6.2\0"
}

#[cfg(CONFIG_APPLE_SEP_KUNIT_TEST)]
#[kernel::macros::kunit_tests(apple_sep_j613_firmware)]
mod j613_firmware_tests {
use super::*;

#[test]
fn exact_os_firmware_only() {
assert!(os_firmware_26_6_2(b"26.6.2"));
assert!(os_firmware_26_6_2(b"26.6.2\0"));
for raw in [&b"14.8.3"[..], &b"26.6.20"[..], &b"27.0"[..], &b""[..]] {
assert!(!os_firmware_26_6_2(raw));
}
}
}
Loading
Loading