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
24 changes: 12 additions & 12 deletions ct.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2737,8 +2737,8 @@ name = "x86_64-unknown-linux-gnu"
group = "linux"
backend = "llvm"
linker = "platform-default-unpinned"
compiler_api_item_count = 2230
compiler_api_sha256 = "671da8ccb1855d450418dc6fc3e79c9b9a2d50c518f98761d8c0fda6abb7c3b3"
compiler_api_item_count = 2236
compiler_api_sha256 = "ec37f397970ac2d9bce6c5188c48c0e1dfbd9b1d321674bce13395acdd6781f8"
claim = "ct-intended"
physical_timing = "required"
binsec = "required"
Expand All @@ -2749,8 +2749,8 @@ name = "aarch64-unknown-linux-gnu"
group = "linux"
backend = "llvm"
linker = "platform-default-unpinned"
compiler_api_item_count = 2224
compiler_api_sha256 = "2bc45c4c1aa47db7c9786ca5aae449cfc7e4370899841c96efbaeb7b67a909ae"
compiler_api_item_count = 2230
compiler_api_sha256 = "2f64f9277c6acbb0510f9b6bb2753b6adcf862f6e8f2945831c5b7607d0a9240"
claim = "ct-intended"
physical_timing = "required"
binsec = "required"
Expand Down Expand Up @@ -2809,8 +2809,8 @@ name = "aarch64-apple-darwin"
group = "macos"
backend = "llvm"
linker = "apple-ld-unpinned"
compiler_api_item_count = 2224
compiler_api_sha256 = "2bc45c4c1aa47db7c9786ca5aae449cfc7e4370899841c96efbaeb7b67a909ae"
compiler_api_item_count = 2230
compiler_api_sha256 = "2f64f9277c6acbb0510f9b6bb2753b6adcf862f6e8f2945831c5b7607d0a9240"
claim = "ct-intended"
physical_timing = "required"
binsec = "unsupported"
Expand All @@ -2834,8 +2834,8 @@ name = "s390x-unknown-linux-gnu"
group = "ibm"
backend = "llvm"
linker = "platform-default-unpinned"
compiler_api_item_count = 2223
compiler_api_sha256 = "e54c2a119d506935fda2279f7d7f9f75506ce86fe5b0b6fc72fd08a7e8090883"
compiler_api_item_count = 2229
compiler_api_sha256 = "8c5e606f4792a7a5052da0e00093fbaa01f56f2223264b7df67bc3ada774d4d5"
claim = "ct-intended"
physical_timing = "required"
binsec = "unsupported"
Expand All @@ -2847,8 +2847,8 @@ name = "powerpc64le-unknown-linux-gnu"
group = "ibm"
backend = "llvm"
linker = "platform-default-unpinned"
compiler_api_item_count = 2223
compiler_api_sha256 = "e85c77d60d67a4648efd50cda101b8248026eb57d9008ceaae2511e319b502d9"
compiler_api_item_count = 2229
compiler_api_sha256 = "24448b0c3dc339211793edc2999bcb77b57956ddde4c1d1111247c52067b9c9f"
claim = "ct-intended"
physical_timing = "required"
binsec = "unsupported"
Expand All @@ -2860,8 +2860,8 @@ name = "riscv64gc-unknown-linux-gnu"
group = "linux"
backend = "llvm"
linker = "platform-default-unpinned"
compiler_api_item_count = 2223
compiler_api_sha256 = "119e6aef49beac534d7155cba8b15a7774c7a4fb6990c9e304b07998844a0858"
compiler_api_item_count = 2229
compiler_api_sha256 = "3d1b7cfa425696e8d060773d2f2778119ce27b8aac3f69daaef1c24ddfb6e677"
claim = "ct-intended"
physical_timing = "required"
binsec = "unsupported"
Expand Down
7 changes: 4 additions & 3 deletions docs/constant-time.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,10 @@ opaque authentication success/failure result may leak.
Secret-bearing fixed-size keys, shared secrets, authentication tags, keypairs,
and keyed outputs do not implement `PartialEq` or `Eq`. Their inherent `ct_eq`
methods return `CtDecision`, an opaque, non-`Copy` value with no public
constructor, formatting, equality, or implicit boolean conversion. Decisions
can be composed with bitwise `&`, `|`, and `!`; the consuming `declassify()`
method is the only public route to a branchable equality bit.
constructor, equality, or implicit boolean conversion. Its `Debug` output is
the fixed redacted string `CtDecision(..)` and does not expose the decision.
Decisions can be composed with bitwise `&`, `|`, and `!`; the consuming
`declassify()` method is the only public route to a branchable equality bit.

Verification APIs keep that boundary inside the primitive and return one opaque
`Result`. Public keys, nonces, signatures, and ciphertext containers are public
Expand Down
8 changes: 4 additions & 4 deletions scripts/ct/artifacts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ fi
OUT_DIR="$ROOT/target/ct/$TARGET/$PROFILE"
ARTIFACT_DIR="$OUT_DIR/artifacts"
BUILD_TARGET_DIR="$ROOT/target/ct-build/$TARGET/$PROFILE"
DEPS_DIR="$BUILD_TARGET_DIR/$TARGET/$PROFILE/deps"
EMIT_ROOT="$BUILD_TARGET_DIR/$TARGET/$PROFILE"
rm -rf "$OUT_DIR"
rm -rf "$BUILD_TARGET_DIR"
mkdir -p "$ARTIFACT_DIR"
Expand All @@ -138,7 +138,7 @@ LIB_EMITTED=()
while IFS= read -r artifact; do
LIB_EMITTED+=("$artifact")
done < <(
find "$DEPS_DIR" -maxdepth 1 -type f \
find "$EMIT_ROOT" -type f \
\( -name 'rscrypto_ct_harness*.ll' \
-o -name 'rscrypto_ct_harness*.s' \
-o -name 'rscrypto_ct_harness*.o' \
Expand All @@ -147,7 +147,7 @@ done < <(
)

if [[ ${#LIB_EMITTED[@]} -eq 0 ]]; then
echo "no CT harness emitted artifacts found in $DEPS_DIR" >&2
echo "no CT harness emitted artifacts found under $EMIT_ROOT" >&2
exit 1
fi
if [[ ${#LIB_EMITTED[@]} -ne 3 ]]; then
Expand Down Expand Up @@ -201,7 +201,7 @@ BIN_EMITTED=()
while IFS= read -r artifact; do
BIN_EMITTED+=("$artifact")
done < <(
find "$DEPS_DIR" -maxdepth 1 -type f \
find "$EMIT_ROOT" -type f \
\( -name 'rscrypto_ct_evidence*.ll' \
-o -name 'rscrypto_ct_evidence*.s' \
-o -name 'rscrypto_ct_evidence*.o' \
Expand Down
30 changes: 30 additions & 0 deletions scripts/ct/evidence_validation_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,36 @@ def main() -> None:
configure_target_environment("powerpc64le-unknown-linux-gnu", unrelated_environment)
assert unrelated_environment == {}

captured_rustdoc: dict[str, object] = {}
original_run = manifest_validation.subprocess.run

def capture_rustdoc(command, **kwargs):
captured_rustdoc["command"] = command
captured_rustdoc["env"] = kwargs.get("env")
return subprocess.CompletedProcess(command, 1, "", "rustdoc unavailable")

manifest_validation.subprocess.run = capture_rustdoc
try:
with tempfile.TemporaryDirectory() as temporary:
inventory_errors: list[str] = []
assert (
manifest_validation.compiler_public_api_snapshot(
Path(temporary),
"aarch64-apple-darwin",
("rscrypto::auth",),
inventory_errors,
)
is None
)
assert inventory_errors == ["compiler public-API inventory failed: rustdoc unavailable"]
finally:
manifest_validation.subprocess.run = original_run

rustdoc_env = captured_rustdoc["env"]
assert isinstance(rustdoc_env, dict)
assert rustdoc_env["RUSTC_BOOTSTRAP"] == "rscrypto"
assert captured_rustdoc["command"][-4:] == ["-Z", "unstable-options", "--output-format", "json"]

commit = "a" * 40
validate_exact_candidate("1.2.3", commit, "1.2.3", commit)
expect_failure(lambda: validate_exact_candidate("1.2.3", commit, "1.2.4", commit))
Expand Down
7 changes: 6 additions & 1 deletion scripts/ct/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import argparse
import hashlib
import json
import os
import re
import subprocess
import sys
Expand Down Expand Up @@ -242,7 +243,11 @@ def compiler_public_api_snapshot(
"--output-format",
"json",
]
completed = subprocess.run(command, cwd=root, capture_output=True, text=True, check=False)
rustdoc_env = os.environ.copy()
# rustdoc JSON is unstable even when the selected release compiler supports it. Scope the escape hatch to
# rscrypto so the inventory describes the exact compiler used by this CT evidence lane.
rustdoc_env["RUSTC_BOOTSTRAP"] = "rscrypto"
completed = subprocess.run(command, cwd=root, capture_output=True, text=True, check=False, env=rustdoc_env)
if completed.returncode != 0:
detail = completed.stderr.strip().splitlines()
suffix = f": {detail[-1]}" if detail else ""
Expand Down
8 changes: 4 additions & 4 deletions src/auth/mlkem/portable/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ unsafe extern "C" {
input2: *const u8,
caps: *const usize,
) -> u64;
#[cfg(any(test, feature = "diag"))]
#[cfg(test)]
fn rscrypto_mlkem_rej_uniform_3blocks_aarch64_linux(out: *mut u16, input: *const u8) -> usize;
#[cfg(any(test, feature = "diag"))]
#[cfg(test)]
fn rscrypto_mlkem_basemul_accumulate_aarch64_linux(
acc: *mut u16,
a: *const u16,
Expand Down Expand Up @@ -187,7 +187,7 @@ pub(super) unsafe fn sample_ntt_rej_uniform_triple_block_bounded_asm(
unpack_triple_counts(packed)
}

#[cfg(all(any(test, feature = "diag"), target_os = "linux"))]
#[cfg(all(test, target_os = "linux"))]
#[inline]
pub(super) unsafe fn sample_ntt_rej_uniform_3blocks_asm(out: *mut u16, input: *const u8) -> usize {
// SAFETY: Linux aarch64 three-block SampleNTT rejection parser call because:
Expand All @@ -200,7 +200,7 @@ pub(super) unsafe fn sample_ntt_rej_uniform_3blocks_asm(out: *mut u16, input: *c
}

#[inline]
#[cfg(any(test, feature = "diag", target_os = "macos"))]
#[cfg(any(test, target_os = "macos"))]
/// # Safety
///
/// The active platform must provide the matching ML-KEM AArch64 assembly
Expand Down
6 changes: 6 additions & 0 deletions src/checksum/common/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ where
/// Test that combine produces crc(A || B) from crc(A) and crc(B).
///
/// This is the fundamental combine property that enables parallel CRC computation.
#[cfg(not(miri))]
#[inline]
pub(in crate::checksum) fn test_combine_property(data: &[u8], split: usize) {
let split = split.checked_rem(data.len()).unwrap_or(0);
Expand Down Expand Up @@ -63,6 +64,7 @@ where
}

/// Test combine with empty second part (identity case).
#[cfg(not(miri))]
#[inline]
pub(in crate::checksum) fn test_combine_empty_suffix(data: &[u8]) {
let crc_data = C::checksum(data);
Expand All @@ -73,6 +75,7 @@ where
}

/// Test combine with empty first part.
#[cfg(not(miri))]
#[inline]
pub(in crate::checksum) fn test_combine_empty_prefix(data: &[u8]) {
let crc_empty = C::checksum(&[]);
Expand All @@ -98,6 +101,7 @@ where
}

/// Test streaming with byte-at-a-time updates.
#[cfg(not(miri))]
#[inline]
pub(in crate::checksum) fn test_streaming_byte_at_a_time(data: &[u8]) {
let oneshot = C::checksum(data);
Expand All @@ -112,6 +116,7 @@ where
}

/// Test streaming across a specific chunk size boundary.
#[cfg(not(miri))]
#[inline]
pub(in crate::checksum) fn test_streaming_chunked(data: &[u8], chunk_size: usize) {
if chunk_size == 0 {
Expand Down Expand Up @@ -167,6 +172,7 @@ where
/// 1. Streaming first half
/// 2. Computing second half separately
/// 3. Combining the results
#[cfg(not(miri))]
#[inline]
pub(in crate::checksum) fn test_streaming_and_combine(data: &[u8]) {
if data.is_empty() {
Expand Down
4 changes: 2 additions & 2 deletions src/checksum/crc64/portable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ use crate::checksum::common::portable;

/// CRC-64-XZ slice-by-8 computation.
#[inline]
#[cfg(all(test, any(target_arch = "x86_64", target_arch = "aarch64")))]
#[cfg(all(test, not(miri), any(target_arch = "x86_64", target_arch = "aarch64")))]
pub(super) fn crc64_slice8_xz(crc: u64, data: &[u8]) -> u64 {
crc64_slice8(crc, data, &kernel_tables::XZ_TABLES_8)
}

/// CRC-64-NVME slice-by-8 computation.
#[inline]
#[cfg(all(test, any(target_arch = "x86_64", target_arch = "aarch64")))]
#[cfg(all(test, not(miri), any(target_arch = "x86_64", target_arch = "aarch64")))]
pub(super) fn crc64_slice8_nvme(crc: u64, data: &[u8]) -> u64 {
crc64_slice8(crc, data, &kernel_tables::NVME_TABLES_8)
}
Expand Down
2 changes: 1 addition & 1 deletion src/hashes/crypto/keccak.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ fn read_unaligned_block_lane<const RATE: usize>(block: &[u8; RATE], lane: usize)
///
/// Since `RATE` is a const generic, `RATE / 8` is compile-time known and LLVM
/// eliminates all `if lane < lanes` branches — the result is straight-line code.
#[cfg(target_arch = "aarch64")]
#[cfg(all(target_arch = "aarch64", not(miri)))]
#[inline]
fn keccakf_absorb_portable<const RATE: usize>(state: &mut [u64; 25], block: &[u8; RATE]) {
debug_assert_eq!(RATE % 8, 0);
Expand Down
4 changes: 2 additions & 2 deletions src/hashes/fast/xxh3/kernels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl Xxh3KernelId {

/// Long-path-only entry for 64-bit hash (>240B, no ≤240B length checks).
#[cfg(any(
test,
all(test, not(miri)),
not(any(
all(target_arch = "x86_64", any(target_feature = "avx512f", target_feature = "avx2")),
all(target_arch = "aarch64", target_feature = "neon"),
Expand All @@ -69,7 +69,7 @@ pub(crate) fn hash64_long_fn(id: Xxh3KernelId) -> fn(&[u8], u64) -> u64 {

/// Long-path-only entry for 128-bit hash (>240B, no ≤240B length checks).
#[cfg(any(
test,
all(test, not(miri)),
not(any(
all(target_arch = "x86_64", any(target_feature = "avx512f", target_feature = "avx2")),
all(target_arch = "aarch64", target_feature = "neon"),
Expand Down
Loading