node identity bound into the keys, two mirror fixes published
with node authentication on, the identity of a node now takes part in the keys of its setup and its links, the client checks every bundle of a mirror on its own, and two security advisories about the descriptor mirror are fixed and published.
two changes to how a client gets and trusts node keys reached the main branch. no byte on the wire changed, and the numbers on the research page are the same preliminary series as before.
the identity of a node is part of its keys
the last change bound every key to the transcript of its exchange, but it bound keys, not the identity of a node. now, when nodes are authenticated, the setup transcript of every hop and the transcript of every authenticated link also hold the node’s identity key, the signing key its certificate certifies. a setup layer and a link open only at the node that holds the private key and binds that identity. a node that copies another node’s onion key or link key into its own descriptor gains nothing from it.
the scheme version moves to v2. there is no version negotiation: older nodes and clients do not work with the new ones, and they are updated together. a node with node authentication and a client or node without it agree on no key either.
the client checks every bundle on its own
the client asks its entry for the signed bundles of every node it lists. it used to check them as
one set and refuse the whole mirror when one bundle failed or two nodes repeated a key. now it
checks every bundle on its own: a listed bundle that fails the check counts as a node the entry
left out, within the same bound (-missing, one by default), and the entry’s own bundle must
pass. bundles of different nodes are no longer compared with each other: the identity binding
above makes a repeated key useless.
a node now lists a peer’s bundle in its mirror only from its start on the node’s clock until a margin before it expires, the allowed clock skew plus the time a request may take. outside that window the peer counts as a node left out. the descriptor lifetime has a lower bound, so a peer that signs again on time stays in every mirror while the clocks agree within the allowance.
two advisories, fixed and published
- GHSA-pwfj-76v6-hcch, medium: a rogue roster node that repeated another node’s onion key in its descriptor made clients refuse every honest mirror, so a client kept drawing until it entered through that node. fixed by the identity binding and the per-bundle check. found by code review, not exercised on the testbed.
- GHSA-5fcf-5qcm-q8vq, low: a descriptor at the edge of its expiry made a client whose clock ran slightly ahead refuse an honest mirror. with equal clocks, as on the single-host testbed, the window was closed. fixed by the mirror margin.
also merged
- the client stops sending once its link ends, and a frame from its entry that does not open closes the circuit as a refusal of its own.
- the key memory tests fail in ci on linux when they cannot lock the pages or read their flags, instead of being skipped.
- a failed onion key rotation is logged as a fixed class, with no text of the underlying error.
how it was checked
- golden vectors on both suites, with and without an identity key.
- tests on both suites: a setup layer and a link bound to one node do not open at another node holding the same key, nor with the identity at one side only; a chain delivers only through nodes that bind the identities named for them.
- client tests: a failing listed bundle counts as left out within the bound, a failing or missing entry bundle refuses the mirror.
- the changes were deployed to the testbed cluster, every node rolled out together: round trips pass, and a client with a foreign anchor is refused.
what this does not fix
- the address of a node and the hash of its certificate are not part of the transcripts, and without node authentication only keys are bound.
- a rogue entry can still leave a node out of its mirror within the bound, and a node can still show different onion keys to different nodes and so learn whose mirror a client used.
- the responder of a link still does not authenticate the initiator.
the full list is on the limits page and in limitations, the transcripts in crypto, the threats and countermeasures in the threat model.