Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 8 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -265,17 +265,19 @@ toyos-ssh = { path = "build/ssh" }
# `classify`, so the host reading a log volume and `logkeeper` writing it cannot
# disagree about which files on it are `logkeeper`'s.
toyos-wallclock = { path = "lib/wallclock" }
# Every SHA-256 the build takes (`toyos_build::sha256`).
toyos-crypto = { path = "lib/crypto" }
# Every SHA-256 the build takes (`toyos_build::sha256`), and the TLS provider of
# every request it makes (`release::agent`).
toyos-crypto = { path = "lib/crypto", features = ["std", "rustls-provider"] }
# The provider's types: its random source and its key-exchange groups.
rustls = { version = "0.23.45", default-features = false }
# The toolchain release's tarball, packed in-process (`build/release.rs`): Rust's
# own tar and gzip, where the binaries are hosts' tools.
tar = { version = "0.4.46", default-features = false }
flate2 = { version = "1", default-features = false, features = ["rust_backend"] }
# Every request the build system makes, GitHub's API and the crates.io index,
# where curl is a host's tool: rustls on ring, the one TLS provider the tree
# takes (`issues/the-internet-clients-work-unchanged.md`), whose C
# and assembly the host's `cc` compiles.
ureq = { version = "3", default-features = false, features = ["rustls"] }
# where curl is a host's tool: rustls on toyos-crypto's provider, with webpki's
# roots.
ureq = { version = "3", default-features = false, features = ["rustls-no-provider", "rustls-webpki-roots"] }
# The authorities `build::trust_roots` writes to ROOT, as the rustls project
# publishes the Mozilla root program, and the PEM it writes them in.
webpki-root-certs = "1"
Expand Down
7 changes: 6 additions & 1 deletion apps/doom/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ softbuffer = { version = "0.4", default-features = false, features = ["wayland",

[build-dependencies]
cc = "1.1"
ureq = { version = "3", default-features = false, features = ["rustls"] }
# doomgeneric's source, over rustls on toyos-crypto's provider with webpki's
# roots, its entropy the host's.
ureq = { version = "3", default-features = false, features = ["rustls-no-provider", "rustls-webpki-roots"] }
toyos-crypto = { path = "../../lib/crypto", features = ["std", "rustls-provider"] }
rustls = { version = "0.23.45", default-features = false }
getrandom = "0.3"
flate2 = { version = "1", default-features = false, features = ["rust_backend"] }
tar = "0.4"

Expand Down
23 changes: 22 additions & 1 deletion apps/doom/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,33 @@ fn main() {
println!("cargo:rerun-if-changed=doomgeneric");
}

/// The host's random bytes, which the provider's key exchanges draw.
#[derive(Debug)]
struct SystemRandom;

impl rustls::crypto::SecureRandom for SystemRandom {
fn fill(&self, bytes: &mut [u8]) -> Result<(), rustls::crypto::GetRandomFailed> {
getrandom::fill(bytes).map_err(|_| rustls::crypto::GetRandomFailed)
}
}

static TLS: toyos_crypto::rustls_provider::Backend = toyos_crypto::rustls_provider::Backend::new(&SystemRandom);

/// toyos-crypto's provider, exchanging keys on X25519 alone, hybrid or not,
/// as the build's own client does (`build/release.rs`).
fn tls_provider() -> std::sync::Arc<rustls::crypto::CryptoProvider> {
let mut provider = TLS.provider();
provider.kx_groups.retain(|group| matches!(group.name(), rustls::NamedGroup::X25519MLKEM768 | rustls::NamedGroup::X25519));
std::sync::Arc::new(provider)
}

/// Root `CLAUDE.md`'s: the only `User-Agent` ToyOS sends.
const USER_AGENT: &str = "toyos-build (https://github.com/ToyOSOrg/ToyOS)";

fn download_doomgeneric(root: &Path) {
println!("Downloading doomgeneric {DOOMGENERIC_COMMIT}...");
let agent = ureq::Agent::config_builder().user_agent(USER_AGENT).build().new_agent();
let tls = ureq::tls::TlsConfig::builder().unversioned_rustls_crypto_provider(tls_provider()).build();
let agent = ureq::Agent::config_builder().user_agent(USER_AGENT).tls_config(tls).build().new_agent();
// The commit is the checksum: GitHub's archive of a sha is that sha's tree
// and can be nothing else, so pinning the URL needs no second hash of ours.
let resp = agent
Expand Down
28 changes: 25 additions & 3 deletions build/release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,33 @@ fn on_runner() -> bool {
std::env::var("GITHUB_ACTIONS").is_ok_and(|v| v == "true")
}

/// The HTTP client of every request the build system makes: rustls on ring
/// with webpki's roots, as ureq configures it; a status is an answer, not an
/// The HTTP client of every request the build system makes: rustls on
/// toyos-crypto's provider with webpki's roots; a status is an answer, not an
/// error.
pub(crate) fn agent() -> ureq::Agent {
ureq::Agent::config_builder().user_agent(USER_AGENT).http_status_as_error(false).build().new_agent()
let tls = ureq::tls::TlsConfig::builder().unversioned_rustls_crypto_provider(tls_provider()).build();
ureq::Agent::config_builder().user_agent(USER_AGENT).http_status_as_error(false).tls_config(tls).build().new_agent()
}

/// The system's random bytes, which the provider's key exchanges draw.
#[derive(Debug)]
struct SystemRandom;

impl rustls::crypto::SecureRandom for SystemRandom {
fn fill(&self, bytes: &mut [u8]) -> Result<(), rustls::crypto::GetRandomFailed> {
getrandom::fill(bytes).map_err(|_| rustls::crypto::GetRandomFailed)
}
}

static TLS: toyos_crypto::rustls_provider::Backend = toyos_crypto::rustls_provider::Backend::new(&SystemRandom);

/// toyos-crypto's provider, exchanging keys on X25519 alone, hybrid or not:
/// no P-256 or P-384 secret meets a server's input while the T14 measures
/// those curves leaking (`issues/toyos-crypto-is-in-the-tree-on-par-with-ring-and-secure.md`).
fn tls_provider() -> std::sync::Arc<rustls::crypto::CryptoProvider> {
let mut provider = TLS.provider();
provider.kx_groups.retain(|group| matches!(group.name(), rustls::NamedGroup::X25519MLKEM768 | rustls::NamedGroup::X25519));
std::sync::Arc::new(provider)
}

/// Whether this job is main's publisher — [`PUBLISHER`] on main, scheduled or
Expand Down
2 changes: 1 addition & 1 deletion issues/the-build-runs-host-tools-outside-rust-and-qemu.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ arrives and is not one. M4 and M5 are stages of `issues/toyos-builds-itself.md`.
| `git` for worktrees, submodules, checkouts, fixtures and rustc's bootstrap | adds worktrees (`build/sysroot.rs`); updates submodules (`src/lib.rs`, `build/sysroot.rs`); fetches the fork from the primary's and checks it out (`build/sysroot.rs`); makes the tests' fixture repositories; runs inside rustc's bootstrap | admitted: no Rust tool does the job, gitoxide 0.85 adds, removes and prunes no worktree, updates no submodule, stages, resets and pushes nothing, checks out only a fresh clone and fetches a local path by spawning `git`; a fixture must be what `git` makes, and bootstrap runs `git` itself | M4 runs it in the guest |
| `git` for reads, a config write, a commit's paths written out, and clones and fetches over HTTPS | `rev-parse`, `merge-base`, `ls-tree`, `ls-files`, `cat-file`, `config --get-regexp`, `config --blob`, `status`, `diff`, `ls-remote` and `grep`, in the build system and its tests; `config --global --add safe.directory` in CI's containers; `checkout <commit> -- <paths>` through an index of its own, which writes the C++ runtime's sources out of the LLVM commit into the stored LLVM, and the ToyOS-hosted clang's out of it into its build (`build/llvm.rs`, `build/hostedclang.rs`); every workflow's checkout | refused: a Rust tool does it, gitoxide 0.85, which reads refs, objects, the index, config, worktrees and status, adds a value to a config file and writes it (gix-config 0.58's `File::section_mut_or_create_new`, `SectionMut::push`, `File::write_to`), walks history, diffs, and lists, fetches and clones a remote over HTTPS; `grep` is a search of the files its index names; and gitoxide's CLI 0.59 (gix 0.88) wrote the runtimes' sources of LLVM `849da7d6` into an empty directory, each path's tree through `gix rev parse`, `gix index from-tree` and `gix free index checkout-exclusive`, exit 0 each: the 18759 files `git` writes there, byte for byte and mode for mode | those are gitoxide's |
| `git log` and `git status` for os-release | the commit, its committer time and whether the tree is that commit's, which `build/build.rs`'s `release` writes into `/system/etc/os-release` in every image build | admitted: the owner's ruling on the dependency audit (2026-10-09), "Drop gix, use git", which covers these two reads and nothing else this table names: they were gitoxide's, gitoxide is no tool the build sheds while `git` stays for the worktree row, and for them it held 84 of the root `Cargo.lock`'s packages | M4 runs it in the guest |
| `cc`, `c++` and `ar` on a Linux host, `build-essential` in CI's containers | rustc links every host binary through `cc`; `cc` and `c++` compile LLVM, clang, LLD and `rustc_llvm` (`build/llvm.rs` names both to bootstrap), and the tablegens of the ToyOS-hosted clang's `NATIVE` build (`build/hostedclang.rs`); `cc` compiles ring's C and assembly in every build of the build system itself, whose HTTP agent is rustls on ring (`build/release.rs`), and in every build of doom's build script, whose download of doomgeneric is `ureq` on rustls on ring (`apps/doom/build.rs`), and in every `--ci host` run as `toyos-crypto`'s dev-dependency oracle (`lib/crypto`); `ar` archives what `cc::Build` compiles, ring's included | admitted: no Rust tool compiles C or C++, or takes rustc's host link; ring is the one TLS provider the tree takes (owner, 2026-10-02), over a provider in Rust alone | M5: no host in the loop |
| `cc`, `c++` and `ar` on a Linux host, `build-essential` in CI's containers | rustc links every host binary through `cc`; `cc` and `c++` compile LLVM, clang, LLD and `rustc_llvm` (`build/llvm.rs` names both to bootstrap), and the tablegens of the ToyOS-hosted clang's `NATIVE` build (`build/hostedclang.rs`); `cc` compiles ring's C and assembly in every `--ci host` run, as the dev-dependency oracle of `toyos-crypto` and `toyos-update` (`lib/crypto`, `lib/update`); `ar` archives what `cc::Build` compiles, ring's included | admitted: no Rust tool compiles C or C++, or takes rustc's host link; ring is the independent oracle the crypto crate is held to, and the build's own HTTP agent and doom's build script are on `toyos-crypto`'s provider (#1020) | M5: no host in the loop |
| the toolchain's own `clang`, `llvm-ar`, `rust-lld` and `llvm-config`, built from `ToyOSOrg/llvm-project` | rustc links every guest binary with `rust-lld`; `clang` compiles the C corpus (`tests/common/compile.rs`) and, with `llvm-ar`, through `cc::Build` the C of every guest crate that has any (`build/clang.rs`, `build/build.rs`'s `GuestEnv`): doomgeneric, and ring's C and assembly in a test crate's `https_get` and `ring_kat`; rustc's bootstrap asks `llvm-config` how to link LLVM | admitted: our fork's C++, which ToyOS can one day build and run; no Rust tool compiles C, `cc::Build` archives with an `ar`, bootstrap reads LLVM through `llvm-config`, and `CLAUDE.md` links everything with `rust-lld` | M5: no host in the loop |
| `ovmf-generic`, `qemu-efi-aarch64` | the x86-64 and AArch64 UEFI firmware of CI's guest containers (`build/firmware.rs`), packaged by Debian apart from QEMU | admitted: QEMU's own firmware, and no Rust firmware does its job | the instrument's QEMU carries its own firmware |
| `ca-certificates` | the trust store `git` and `curl` verify against in CI's containers | admitted: data both of them need | goes when neither runs there |
Expand Down
29 changes: 18 additions & 11 deletions issues/toyos-crypto-is-in-the-tree-on-par-with-ring-and-secure.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ review has been done, and passing vectors does not show it is safer than ring.
| `system/sshserver` | russh with the RustCrypto stack, including `rsa` (RUSTSEC-2023-0071) | none directly; it reaches the crate through `toyos-ssh` |
| Image and package signing: `lib/update` (the loader, `/system/bin/update`, `build/signing.rs`, `build/root`, #892's repository keys) | the crate's strict Ed25519 and SHA-2, since #1019; signing and a seed's public key behind `sign`, on the host | stage 6's bench readings |
| Every SHA-256: the build, `pkg`, `lib/swap`, `system/update`, `lib/update` and the loader | the crate, since #1016: SHA-NI on x86-64, the UEFI loader's in a block that saves the XMM registers it uses; the Armv8 SHA instructions where the target promises them. No slower than `toyos-sha2-hw`, which it replaces, on either bench: on the T14 4.6 times as fast at 64 B and 9 and 6 percent faster at 16 KiB and 1 MiB, on the AMD bench 2.8 times at 64 B, 2 percent at 16 KiB and equal at 1 MiB (#1016's evidence) | nothing |
| ToyOS's own HTTPS clients. On the host: the build's `ureq` (`build/release.rs`) and doom's build script (`apps/doom/build.rs`). In a guest, none today: `https_tls13` and `pkg install <url>` are stages 3 and 5 of `issues/the-internet-clients-work-unchanged.md` | rustls on `ring`, which is `ToyOSOrg/ring` in a guest | the rustls provider through ureq's `rustls-no-provider` feature. Stage 5, once parity and security hold (owner, 2026-10-13) |
| ToyOS's own HTTPS clients. On the host: the build's `ureq` (`build/release.rs`) and doom's build script (`apps/doom/build.rs`). In a guest, none today: `https_tls13` and `pkg install <url>` are stages 3 and 5 of `issues/the-internet-clients-work-unchanged.md` | the host's two: the crate's rustls provider through ureq's `rustls-no-provider`, since #1020, its key exchange on X25519 and X25519MLKEM768 alone while the T14 finding stands. In a guest, none | the NIST groups back once the T14 finding is resolved |
| Wi-Fi's `wlan` (`issues/there-is-no-wifi.md` P6, W2) | nothing yet | PBKDF2-HMAC-SHA1, the 802.11i PRF and RFC 3394 unwrap, which the crate has. AES-CMAC-128, SAE over P-256 by hash-to-element, a public constant-time comparison and a public wiping secret, which it lacks |
| `issues/programs-hold-aes-keys-as-key-locker-handles.md` | blocked on a session-long AES key | a TLS client on the crate is that consumer: AES behind a Key Locker handle. SSH holds no AES key |

Expand Down Expand Up @@ -474,18 +474,18 @@ Not consumers:
`toyos-sha2` and `toyos-sha2-hw` are deleted; the crate's SHAVS tests
replace theirs. NIST's ACVP vectors moved to `tests/acvp/`, outside the
crate's directory, once the crate entered an image.
- ToyOS's own HTTPS clients use the crate's rustls provider once stages 3
and 4 hold for TLS's primitives. The owner ruled this on 2026-10-13:
the crypto goal overrides his ruling of 2026-10-02 in
`issues/the-internet-clients-work-unchanged.md` stage 3. Until then ring
stays the provider. `ToyOSOrg/ring` stays as a fork so that unmodified
programs build.
- ToyOS's own HTTPS clients use the crate's rustls provider. The owner
ruled on 2026-10-13 that the crypto goal overrides his ruling of
2026-10-02 in `issues/the-internet-clients-work-unchanged.md` stage 3,
and on 2026-10-22 that the tree uses the crate now. The host's two, the
build's agent and doom's build script, take it since #1020, on X25519
groups alone while the T14 finding stands. `ToyOSOrg/ring` stays as a
fork so that unmodified programs build.
- The `https_tls13` metal row passes on it.
- The `cc` row of
`issues/the-build-runs-host-tools-outside-rust-and-qemu.md` stops
naming ring for the build system's HTTP agent. It still names ring as
`lib/crypto`'s dev-dependency oracle, whose C and assembly every
`--ci host` run compiles.
`issues/the-build-runs-host-tools-outside-rust-and-qemu.md` names ring
only as the crate's and `lib/update`'s dev-dependency oracle, whose C
and assembly every `--ci host` run compiles. Done (#1020).
- Wi-Fi's P6 is this crate's AES-CMAC, SAE by hash-to-element, public
constant-time comparison and public wiping secret, each against its RFC
or Annex J vectors.
Expand Down Expand Up @@ -534,6 +534,13 @@ Not consumers:
per-temporary erasure on the T14, 0.79–0.88 on the AMD bench) and a
reviewed contract. Compiler
copies, registers, spills and caller-held bytes are not wiped.
- The host's HTTPS clients exchange keys on X25519 and X25519MLKEM768
alone: no P-256 or P-384 secret meets a server's input while the T14
finding stands, and a server offering only those groups is refused. Each
client keeps the two groups itself (`build/release.rs`,
`apps/doom/build.rs`). **Owner**: this track. **Exit**: stage 4's T14
finding (P-256 key derivation and agreement, and P-384 agreement, leak) is
resolved, and the clients take the provider's groups whole.
- ToyOS's AArch64 targets hash with the portable SHA-2 rounds: no target
promises the Armv8 SHA instructions, and neither the kernel nor the crate
detects them at run time. **Owner**: this track. **Exit**: the crate takes
Expand Down