# Equality comparisons reviewed and allowed in src/.
#
# Checked by scripts/check-comparisons.sh, which fails on anything in src/ that
# is not listed here. Format is <path><TAB><the source line, trimmed>.
#
# The bar for adding a line: the bytes on both sides are public. If either side
# is a signature, a MAC, a proof, a share, or reconstructed key material, it
# does not belong here, it belongs in a constant-time comparison.
#
# None of the three below touch secret material. As of P5-04 this crate holds
# no secret-bearing types at all: every secret stays inside the component.
# Reading a key name out of core/pin.toml. Public build metadata, and the
# comparison is over the key name rather than any value.
src/artifact.rs if name.trim() != key {
# The embedded component's SHA-256 against the hash the package declares. Both
# sides are public: the declared hash ships in the crate and the actual hash is
# computed from bytes anyone can read. This is a build-integrity check against
# a substituted artifact, not authentication of a secret, and an attacker who
# can supply the artifact already knows both values.
src/artifact.rs if actual == declared {
# Looking up a disclosure attribute by name. Attribute names are public by
# design in this API, which is the whole reason disclosure is expressed as
# named attributes rather than a raw bitmask.
src/disclosure.rs .position(|n| n == name)
# Checking the legacy recovery envelope's magic and version. These are public
# structural parsing metadata, not authentication-bearing bytes.
src/identity.rs if bytes.len() < HEADER_BYTES || &bytes[..4] != b"ATHR" || bytes[4] != 1 {
# Validating a public count field while parsing the legacy recovery envelope;
# it is structural metadata, not authentication-bearing data.
src/identity.rs if count == 0 || count > 5 {
# Rejecting trailing bytes after parsing the public recovery-envelope layout;
# this is a structural format check, not an authentication comparison.
src/identity.rs if offset != bytes.len() {
# Ensuring a single-share decoder received one public envelope entry; this is
# a structural parsing count check, not authentication-bearing data.
src/identity.rs if set.shares.len() != 1 {
# Checking that a projection the component returned carries the vendored
# parameter set's coefficient count. The length of a public projection vector
# is public structural metadata: public_b is published material, and its size
# is fixed by the module rank the artifact was built at rather than by any
# secret. Nothing branches on a coefficient value, only on how many there are,
# so there is no secret-dependent timing signal to leak.
src/identity.rs if inner.public_b.len() != PROJECTION_COEFFICIENTS {
# Typed-API validation before handing public material to the component. These
# compare a public algorithm label, or the length of a public key or signature,
# against the ML-DSA-65 constants. The algorithm enum and the lengths are public
# structural metadata; no secret bytes are compared and nothing branches on a
# key or signature value. The bytes themselves are verified inside the component.
src/identity.rs if public_key.algorithm != SigAlgorithm::MlDsa65 {
src/identity.rs if public_key.as_bytes().len() != SigAlgorithm::MlDsa65.public_key_size() {
src/identity.rs if signature.algorithm != SigAlgorithm::MlDsa65 {
src/identity.rs if signature.as_bytes().len() != SigAlgorithm::MlDsa65.signature_size() {
# Looking a purpose up by its registry name. Both sides are public: the name a
# caller asks for and the names the component lists. Nothing secret is compared
# and no key or signature is involved.
src/purpose.rs .find(|p| p.name == name)