123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820 |
- Filename: 202-improved-relay-crypto.txt
- Title: Two improved relay encryption protocols for Tor cells
- Author: Nick Mathewson
- Created: 19 Jun 2012
- Status: Meta
- Note: This is an important development step in improving our relay
- crypto, but it doesn't actually say how to do this.
- Overview:
- This document describes two candidate designs for a better Tor
- relay encryption/decryption protocol, designed to stymie tagging
- attacks and better accord with best practices in protocol design.
- My hope is that readers will examine these protocols, evaluate their
- security and practicality, improve on them, and help to pick one for
- implementation in Tor.
- In section 1, I describe Tor's current relay crypto protocol, its
- drawbacks, how it fits in with the rest of Tor, and some
- requirements/desiderata for a replacement. In sections 2 and 3, I
- propose two alternative replacements for this protocol. In section
- 4, I discuss their pros and cons.
- 1. Background and Motivation
- 1.0. A short overview of Tor's current protocols
- The core pieces of the Tor protocol are the link protocol,
- the circuit extend protocol, the relay protocol, and the stream
- protocol. All are documented in [TorSpec].
- Briefly:
- - The link protocol handles all direct pairwise communication
- between nodes. Everything else is transmitted over it. It
- uses TLS.
- - The circuit extend protocol uses public-key crypto to set up
- multi-node virtual tunnels, called "circuits", from a client
- through one or more nodes.
- *** The relay protocol uses established circuits to communicate
- from a client to a node on a circuit. That's the one we'll
- be talking about here. ***
- - The stream protocol is tunneled over relay protocol; clients
- use it to tell servers to open anonymous TCP connections, to
- send data, and so forth. Servers use it to report success or
- failure opening anonymous TCP connections, to send data from
- TCP connections back to clients, and so forth.
- In more detail: The link protocol's job is to connect two
- computers with an encrypted, authenticated stream, to
- authenticate one or both of them to the other, and to provide a
- channel for passing "cells" between them. The circuit extend
- protocol's job is to set up circuits: persistent tunnels that
- connect a Tor client to an exit node through a series of
- (typically three) hops, each of which knows only the previous and
- next hop, and each of which has a set of keys that they share
- only with the client. Finally, the relay protocol's job is to
- allow a client to communicate bidirectionally with the node(s) on
- the circuit, once their shared keys have been established.
- (We'll ignore the stream protocol for the rest of this document.)
- Note on terminology: Tor nodes are sometimes called "servers",
- "relays", or "routers". I'll use all these terms more or less
- interchangeably. For simplicity's sake, I will call the party
- who is constructing and using a circuit "the client" or "Alice",
- even though nodes sometimes construct circuits too.
- Tor's internal packets are called "cells". All the cells we deal
- with here are 512 bytes long.
- The nodes in a circuit are called its "hops"; most circuits are 3
- hops long. This doesn't include the client: when Alice builds a
- circuit through nodes Bob_1, Bob_2, and Bob_3, the first hop is
- "Bob_1" and the last hop is "Bob_3".
- 1.1. The current relay protocol and its drawbacks
- [This section describes Tor's current relay protocol. It is not a
- proposal; rather it is what we do now. Sections 2 and 3 have my
- proposed replacements for it.]
- A "relay cell" is a cell that is generated by the client to send
- to a node, or by a node to send to the client. It's called a
- "relay" cell because a node that receives one may need to relay
- it to the next or previous node in the circuit (or to handle the
- cell itself).
- A relay cell moving towards the client is called "inbound"; a
- cell moving away is called "outbound".
- When a relay cell is constructed by the client, the client adds one
- layer of crypto for each node that will process the cell, and gives
- the cell to the first node in the circuit. Each node in turn then
- removes one layer of crypto, and either forwards the cell to the next
- node in the circuit or acts on that cell itself.
- When a relay cell is constructed by a node, it encrypts it and sends
- it to the preceding node in the circuit. Each node between the
- originating node and the client then encrypts the cell and passes it
- back to the preceding node. When the client receives the cell, it
- removes layers of crypto until it has an unencrypted cell, which it
- then acts on.
- In the current protocol, the body of each relay cell contains, in
- its unencrypted form:
- Relay command [1 byte]
- Zeros [2 bytes]
- StreamID [2 bytes]
- Digest [4 bytes]
- Length [2 bytes]
- Data [498 bytes]
- (This only adds up to 509 bytes. That's because the Tor link
- protocol transfers 512-byte cells, and has a 3 byte overhead per
- cell. Not how we would do it if we were starting over at this
- point.)
- At every node of a circuit, the node relaying a cell
- encrypts/decrypts it with AES128-CTR. If the cell is outbound
- and the "zeros" field is set to all-zeros, the node additionally
- checks whether 'digest' is correct. A correct digest is the
- first 4 bytes of the running SHA1 digest of: a shared secret,
- concatenated with all the relay cells destined for this node on
- this circuit so far, including this cell. If _that's_ true, then
- the node accepts this cell. (See section 6 of [TorSpec] for full
- detail; see section A.1 for a more rigorous description.)
- The current approach has some actual problems. Notably:
- * It permits tagging attacks. Because AES_CTR is an XOR-based
- stream cipher, an adversary who controls the first node in a
- circuit can XOR anything he likes into the relay cell, and
- then see whether he/she encounters a correspondingly
- defaced cell at some exit that he also controls.
- That is, the attacker picks some pattern P, and when he
- would transmit some outbound relay cell C at hop 1, he
- instead transmits C xor P. If an honest exit receives the
- cell, the digest will probably be wrong, and the honest exit
- will reject it. But if the attacker controls the exit, he
- will notice that he has received a cell C' where the digest
- doesn't match, but where C' xor P _does_ have a good digest.
- The attacker will then know that his two nodes are on the
- same circuit, and thereby be able to link the user (whom the
- first node sees) to her activities (which the last node sees).
- Back when we did the Tor design, this didn't seem like a
- big deal, since an adversary who controls both the first and
- last node in a circuit is presumed to win already based on
- traffic correlation attacks. This attack seemed strictly
- worse than that, since it was trivially detectable in the
- case where the attacker _didn't_ control both ends. See
- section 4.4 of the Tor paper [TorDesign] for our early
- thoughts here; see Xinwen Fu et al's 2009 work for a more
- full explanation of the in-circuit tagging attack [XF]; and
- see "The 23 Raccoons'" March 2012 "Analysis of the Relative
- Severity of Tagging Attacks" mail on tor-dev (and the
- ensuing thread) for a discussion of why we may want to care
- after all, due to attacks that use tagging to amplify route
- capture. [23R]
- It also has some less practical issues.
- * The digest portion is too short. Yes, if you're an attacker
- trying to (say) change an "ls *" into an "rm *", you can
- only expect to get one altered cell out of 2^32 accepted --
- and all future cells on the circuit will be rejected with
- similar probability due to the change in the running hash
- -- but 1/2^32 is a pretty high success rate for crypto attacks.
- * It does MAC-then-encrypt. That makes smart people cringe.
- * Its approach to MAC is H(Key | Msg), which is vulnerable to
- length extension attack if you've got a Merkle-Damgard hash
- (which we do). This isn't relevant in practice right now,
- since the only parties who see the digest are the two
- parties that rely on it (because of the MAC-then-encrypt).
- 1.2. Some feature requirements
- Relay cells can originate at the client or at a relay. Relay cells
- that originate at the client are given to the first node in the
- circuit, and constructed so that they will be decrypted and forwarded
- by the first M-1 nodes in the circuit, and finally decrypted and
- processed by the Mth node, where the client chooses M. (Usually, the
- Mth node is the the last one, which will be an exit node.) Relay
- cells that originate at a hop in the circuit are given to the
- preceding node, and eventually delivered to the client.
- Tor provides a so called "leaky pipe" circuit topology
- [TorDesign]: a client can send a cell to any node in the circuit,
- not just the last node. I'll try to keep that property, although
- historically we haven't really made use of it.
- In order to implement telescoping circuit construction (where the
- circuit is built by iteratively asking the last node in the
- circuit to extend the circuit one hop more), it's vital that the
- last hop of the circuit be able to change.
- Proposal 188 [Prop188] suggests that we implement a "bridge guards"
- feature: making some (non-public) nodes insert an extra hop into
- the circuit after themselves, in a way that will make it harder
- for other nodes in the network to enumerate them. We
- therefore want our circuits to be one-hop re-extensible: when the
- client extends a circuit from Bob1 to Bob2, we want Bob1 to be
- able to introduce a new node "Bob1.5" into the circuit such that
- the circuit runs Alice->Bob1->Bob1.5->Bob2. (This feature has
- been called "loose source routing".)
- Any new approach should be able to coexist on a circuit
- with the old approach. That is, if Alice wants to build a
- circuit through Bob1, Bob2, and Bob3, and only Bob2 supports a
- revised relay protocol, then Alice should be able to build a
- circuit such that she can have Bob1 and Bob3 process each cell
- with the current protocol, and Bob2 process it with a revised
- protocol. (Why? Because if all nodes in a circuit needed to use
- the same relay protocol, then each node could learn information
- about the other nodes in the circuit from which relay protocol
- was chosen. For example, if Bob1 supports the new protocol, and
- sees that the old relay protocol is in use, and knows that Bob2
- supports the new one, then Bob1 has learned that Bob3 is some
- node that does not support the new relay protocol.)
- Cell length needs to be constant as cells move through the
- network. For historical reasons mentioned above in section 1.1,
- the length of the encrypted part of a relay cell needs to be 509
- bytes.
- 1.3. Some security requirements
- Two adjacent nodes on a circuit can trivially tell that they are
- on the same circuit, and the first node can trivially tell who
- the client is. Other than that, we'd like any attacker who
- controls a node on the circuit not to have a good way to learn
- any other nodes, even if he/she controls those nodes. [*]
- Relay cells should not be malleable: no relay should be able to
- alter a cell between an honest sender and an honest recipient in
- a way that they cannot detect.
- Relay cells should be secret: nobody but the sender and recipient
- of a relay cell should be able to learn what it says.
- Circuits should resist transparent, recoverable tagging attacks:
- if an attacker controls one node in a circuit and alters a relay
- cell there, no non-adjacent point in the circuit should be able
- to recover the relay cell as it would have received it had the
- attacker not altered it.
- The above properties should apply to sequences of cells too:
- an attacker shouldn't be able to change what sequence of cells
- arrives at a destination (for example, by removing, replaying, or
- reordering one or more cells) without being detected.
- (Feel free to substitute whatever formalization of the above
- requirements makes you happiest, and add whatever caveats are
- necessary to make you comfortable. I probably missed at least
- two critical properties.)
- [*] Of course, an attacker who controls two points on a circuit
- can probably confirm this through traffic correlation. But
- we'd prefer that the cryptography not create other, easier
- ways for them to do this.
- 1.4. A note on algorithms
- This document is deliberately agnostic concerning the choice of
- cryptographic primitives -- not because I have no opinions about
- good ciphers, MACs, and modes of operation -- but because
- experience has taught me that mentioning any particular
- cryptographic primitive will prevent discussion of anything else.
- Please DO NOT suggest algorithms to use in implementing these
- protocols yet. It will distract! There will be time later!
- If somebody _else_ suggests algorithms to use, for goodness' sake
- DON'T ARGUE WITH THEM! There will be time later!
- 2. Design 1: Large-block encryption
- In this approach, we use a tweakable large-block cipher for
- encryption and decryption, and a tweak-chaining function TC.
- 2.1. Chained large-block what now?
- We assume the existence of a primitive that provides the desired
- properties of a tweakable[Tweak] block cipher, taking blocks of any
- desired size. (In our case, the block size is 509 bytes[*].)
- It also takes a Key, and a per-block "tweak" parameter that plays
- the same role that an IV plays in CBC, or that the counter plays
- in counter mode.
- The Tweak-chaining function TC takes as input a previous tweak, a
- tweak chaining key, and a cell; it outputs a new tweak. Its
- purpose is to make future cells undecryptable unless you have
- received all previous cells. It could probably be something like
- a MAC of the old tweak and the cell using the tweak chaining key
- as the MAC key.
- (If the initial tweak is secret, I am not sure that TC needs to
- be keyed.)
- [*] Some large-block cipher constructions use blocks whose size is
- the multiple of some underlying cipher's block size. If we wind
- up having to use one of those, we can use 496-byte blocks instead
- at the cost of 2.5% wasted space.
- 2.2. The protocol
- 2.2.1. Setup phase
- The circuit construction algorithm needs to produce forward and
- backward keys Kf and Kb, the forward and backward tweak chaining
- keys TCKf and TCKb, as well as initial tweak values Tf and Tb.
- 2.2.2. The cell format
- We replace the "Digest" and "Zeros" fields of the cell with a
- single Z-byte "Zeros" field to determine when the cell is
- recognized and correctly decrypted; its length is a security
- parameter.
- 2.2.3. The decryption operations
- For a relay to handle an inbound RELAY cell, it sets Tb_next to
- TC(TCKb, Tb, Cell). Then it encrypts the cell using the large
- block cipher keyed with Kb and tweaked with Tb. Then it sets Tb
- to Tb_next.
- For a relay to handle an outbound RELAY cell, it sets Tf_next to
- TC(TCKf, Tf, Cell). Then it decrypts the cell using the large
- block cipher keyed with Kf and tweaked with Tf. Then it sets Tf
- to Tf_next. Then it checks the 'Zeros' field on the cell;
- if that field is all [00] bytes, the cell is for us.
- 2.3. Security discussion
- This approach is fairly simple (at least, no more complex than
- its primitives) and achieves some of our security goals. Because
- of the large block cipher approach, any change to a cell will
- render that cell undecryptable, and indistinguishable from random
- junk. Because of the tweak chaining approach, if even one cell
- is missed or corrupted or reordered, future cells will also
- decrypt into random junk.
- The tagging attack in this case is turned into a circuit-junking
- attack: an adversary who tries to mount it can probably confirm
- that he was indeed first and last node on a target circuit
- (assuming that circuits which turn to junk in this way are rare),
- but cannot recover the circuit after that point.
- As a neat side observation, note that this approach improves upon
- Tor's current forward secrecy, by providing forward secrecy while
- circuits are still operational, since each change to the tweak
- should make previous cells undecryptable if the old tweak value
- isn't recoverable.
- The length of Zeros is a parameter for what fraction of "random
- junk" cells will potentially be accepted by a router or client.
- If Zeros is Z bytes long, then junk cells will be accepted with
- P < 2^-(8*Z + 7). (The '+7' is there because the top 7 bits of
- the Length field must also be 0.)
- There's no trouble using this protocol in a mixed circuit, where
- some nodes speak the old protocol and some speak the
- large-block-encryption protocol.
- 3. Design 2: short-MAC-and-pad
- In this design, we behave more similarly to a mix-net design
- (such as Mixmaster or Mixminion's headers). Each node checks a
- MAC, and then re-pads the cell to its chosen length before
- decoding the cell.
- This design uses as a primitive a MAC and a stream cipher. It
- might also be possible to use an authenticating cipher mode,
- if we can find one that works like a stream cipher and allows us
- to efficiently output authenticators for the stream so far.
- NOTE TO AE/AEAD FANS: The encrypt-and-MAC model here could be
- replaced with an authenticated encryption mode without too much
- loss of generality.
- 3.1. The protocol
- 3.1.1 Setup phase
- The circuit construction algorithm needs to produce forward and
- backward keys Kf and Kb, forward and backward stream cipher IVs
- IVf and IVb, and forward and backward MAC keys Mf and Mb.
- Additionally, the circuit construction algorithm needs a way for
- the client to securely (and secretly? XXX) tell each hop in the
- circuit a value 'bf' for the number of bytes of MAC it should
- expect on outbound cells and 'bb' for the number of bytes it
- should use on cells it's generating. Each node can get a
- different 'bf' and 'bb'. These values can be 0: if a node's bf
- is 0, it doesn't authenticate cells; if its bb is 0, it doesn't
- originate them.
- The circuit construction algorithm also needs a way to tell each
- the client to securely (and secretly? XXX) tell each hop in the
- circuit whether it is allowed to be the final destination for
- relay cells.
- Set the stream Sf and the stream Sb to empty values.
- 3.1.2. The cell format
- The Zeros and Digest field of the cell format are removed.
- 3.1.3. The relay operations
- Upon receiving an outbound cell, a node removes the first b bytes
- of the cell, and puts them aside as 'M'. The node then computes
- between 0 and 2 MACs of the stream consisting of all previously
- MAC'd data, plus the remainder of the cell:
- If b>0 and there is a next hop, the node computes M_relay.
- If this node was told to deliver traffic, or it is the last
- node in the circuit so far, the node computes M_receive.
- M_relay is computed as MAC(stream | "relay"); M_receive is
- computed as MAC(stream | "receive").
- If M = M_receive, this cell is for the node; it should process
- it.
- If M = M_relay, or if b == 0, this cell should be relayed.
- If a MAC was computed and neither of the above cases was met,
- then the cell is bogus; the node should discard it and destroy
- the circuit.
- The node then removes the first bf bytes of the cell, and pads the
- cell at the end with bf zero bytes. Finally, the node decrypts
- the whole remaining padded cell with the stream cipher.
- To handle an inbound cell, the node simply does a stream cipher
- with no checking.
- 3.1.4. Generating inbound cells.
- To generate an inbound cell, a node makes a 509-bb byte RELAY
- cell C, encrypts that cell with Kb, appends the encrypted cell to
- Sb, and prepends M_receive(Sb) to the cell.
- 3.1.5. Generating outbound cells
- Generating an outbound cell is harder, since we need to know what
- padding the earlier nodes will generate in order to know what
- padding the later nodes will receive and compute their MACs, but
- we also need to know what MACs we'll send to the later nodes in
- order to compute which MACs we'll send to the earlier ones.
- Mixnet clients have needed to do this for ages, though, so the
- algorithms are pretty well settled. I'll give one below in A.3.
- 3.2. Security discussion
- This approach is also simple and (given good parameter choices)
- can achieve our goals. The trickiest part is the algorithm that
- clients must follow to package cells, but that's not so bad.
- It's not necessary to check MACs on inbound traffic, because
- nobody but the client can tell scrambled messages from good ones,
- and the client can be trusted to keep the client's own secrets.
- With this protocol, if the attacker tries to do a tagging attack,
- the circuit should get destroyed by the next node in the circuit
- that has a nonzero "bf" value, with probability == 1-2^-(8*bf).
- (If there are further intervening honest nodes, they also have a
- chance to detect the attack.)
- Similarly, any attempt to replay, or reorder outbound cells
- should fail similarly.
- The "bf" values could reveal to each node its position in the
- circuit and the client preferences, depending on how we set them;
- on the other hand, having a fixed bf value would reveal to the
- last node the length of the circuit. Neither option seems great.
- This protocol doesn't provide any additional forward secrecy
- beyond what Tor has today. We could fix that by changing our use
- of the stream cipher so that instead of running in counter mode
- between cells, we use a tweaked stream cipher and change the
- tweak with each cell (possibly based on the unused portion of the
- MAC).
- This protocol does support loose source routing, so long as
- no padding bytes are added by any router-added nodes.
- In a circuit, every node has at least one relay cell sent to it:
- even non-exit nodes get a RELAY_EXTEND cell.
- 4. Discussion
- I'm not currently seeing a reason to strongly prefer one of these
- approaches over another.
- In favor of large-block encryption:
- - The space overhead seems smaller: we need to use up fewer
- bytes in order to get equivalent looking security.
- (For example, if we want to have P < 2^64 that a cell altered
- by hop 1 could be accepted by hop 2 or hop 3, *and* we want P
- < 2^64 that a cell altered by hop 2 could be accepted by hop
- 3, the large-block approach needs about 8 bytes for the Zeros
- field, whereas the short-MAC-and-pad approach needs 16 bytes
- worth of MACs.)
- - We get forward secrecy pretty easily.
- - The format doesn't leak anything about the length of the
- circuit, or limit it.
- - We don't need complicated logic to set the 'b' parameters.
- - It doesn't need tricky padding code.
- In the favor of short-MAC-and-pad:
- - All of the primitives used are much better analyzed and
- understood. There's nothing esoteric there. The format
- itself is similar to older, well-analyzed formats.
- - Most of the constructions for the large-block-cipher approach
- seem less efficient in CPU cycles than a good stream cipher
- and a MAC. (But I don't want to discuss that now; see section
- 1.4 above!)
- Unclear:
- - Suppose that an attacker controls the first and last hop of a
- circuit, and tries an end-to-end tagging attack. With
- large-block encryption, the tagged cell and all future cells
- on the circuit turn to junk after the tagging attack, with
- P~~100%. With short-MAC-and-pad, the circuit is destroyed at
- the second hop, with P ~~ 1- 2^(-8*bf). Is one of these
- approaches materially worse for the attacker?
- - Can we do better than the "compute two MACs" approach for
- distinguishing the relay and receive cases of the
- short-MAC-and-pad protocol?
- - To what extent can we improve these protocols?
- - If we do short-MAC-and-pad, should we apply the forward
- security hack alluded to in section 3.2?
- 5. Acknowledgments
- Thanks to the many reviewers of the initial drafts of this
- proposal. If you can make any sense of what I'm saying, they
- deserve much of the credit.
- A. Formal description
- Note that in all these cases, more efficient descriptions exist.
- A.1. The current Tor relay protocol.
- Relay cell format:
- Relay command [1 byte]
- Zeros [2 bytes]
- StreamID [2 bytes]
- Digest [4 bytes]
- Length [2 bytes]
- Data [498 bytes]
- Circuit setup:
- (Specified elsewhere; the client negotiates with each router in
- a circuit the secret AES keys Kf, Kb, and the secret 'digest
- keys' Df, and Db. They initialize AES counters Cf and Cb to
- 0. They initialize the digest stream Sf to Df, and Sb to Db.)
- HELPER FUNCTION: CHECK(Cell [in], Stream [in,out]):
- 1. If the Zeros field of Cell is not [00 00], return False.
- 2. Let Cell' = Cell with its Digest field set to [00 00 00 00].
- 3. Let S' = Stream | Cell'.
- 4. If SHA1(S') = the Digest field of Cell, set Stream to S',
- and return True.
- 5. Otherwise return False.
- HELPER FUNCTION: CONSTRUCT(Cell' [in], Stream [in,out])
- 1. Set the Zeros and Digest field of Cell' to [00] bytes.
- 2. Set Stream to Stream | Cell'.
- 3. Construct Cell from Cell' by setting the Digest field to
- SHA1(Stream), and taking all other fields as-is.
- 4. Return Cell.
- HELPER_FUNCTION: ENCRYPT(Cell [in,out], Key [in], Ctr [in,out])
- 1. Encrypt Cell's contents using AES128_CTR, with key 'Key' and
- counter 'Ctr'. Increment 'Ctr' by the length of the cell.
- HELPER_FUNCTION: DECRYPT(Cell [in,out], Key [in], Ctr [in,out])
- 1. Same as ENCRYPT.
- Router operation, upon receiving an inbound cell -- that is, one
- sent towards the client.
- 1. ENCRYPT(cell, Kb, Cb)
- 2. Send the decrypted contents towards the client.
- Router operation, upon receiving an outbound cell -- that is, one
- sent away from the client.
- 1. DECRYPT(cell, Kf, Cf)
- 2. If CHECK(Cell, Sf) is true, this cell is for us. Do not
- relay the cell.
- 3. Otherwise, this cell is not for us. Send the decrypted cell
- to the next hop on the circuit, or discard it if there is no
- next hop.
- Router operation, to create a relay cell that will be delivered
- to the client.
- 1. Construct a Relay cell Cell' with the relay command, length,
- stream ID, and body fields set as appropriate.
- 2. Let Cell = CONSTRUCT(Cell', Sb).
- 3. ENCRYPT(Cell, Kb, Cb)
- 4. Send the encrypted cell towards the client.
- Client operation, receiving an inbound cell.
- For each hop H in a circuit, starting with the first hop and
- ending (possibly) with the last:
- 1. DECRYPT(Cell, Kb_H, Cb_H)
- 2. If CHECK(Cell, Sb_H) is true, this cell was sent from hop
- H. Exit the loop, and return the cell in its current
- form.
- If we reach the end of the loop without finding the right hop,
- the cell is bogus or corrupted.
- Client operation, sending an outbound cell to hop H.
- 1. Construct a Relay cell Cell' with the relay command, length,
- stream ID, and body fields set as appropriate.
- 2. Let Cell = CONSTRUCT(Cell', Sf_H)
- 3. For i = H..1:
- A. ENCRYPT(Cell, Sf_i, Cf_i)
- 4. Deliver Cell to the first hop in the circuit.
- A.2. The large-block-cipher protocol
- Same as A.1, except for the following changes.
- The cell format is now:
- Zeros [Z bytes]
- Length [2 bytes]
- StreamID [2 bytes]
- Relay command [1 byte]
- Data [504-Z bytes]
- Ctr is no longer a counter, but a Tweak value.
- Each key is now a tuple of (Key_Crypt, Key_TC)
- Streams are no longer used.
- HELPER FUNCTION: CHECK(Cell [in], Stream [in,out])
- 1. If the Zeros field of Cell contains only [00] bytes,
- return True.
- 2. Otherwise return false.
- HELPER FUNCTION: CONSTRUCT(Cell' [in], Stream [in,out])
- 1. Let Cell be Cell', with its "Zeros" field set to Z [00]
- bytes.
- 2. Return Cell'.
- HELPER FUNCTION: ENCRYPT(Cell [in,out], Key [in], Tweak [in,out])
- 2. Encrypt Cell using Key and Tweak
- 1. Let Tweak' = TC(Key_TC, Tweak, Cell)
- 3. Set Tweak to Tweak'.
- HELPER FUNCTION: DECRYPT(Cell [in,out], Key [in], Tweak [in,out])
- 1. Let Tweak' = TC(Key_TC, Tweak, Cell)
- 2. Decrypt Cell using Key and Tweak
- 3. Set Tweak to Tweak'.
- A.3. The short-MAC-and-pad protocol.
- Define M_relay(K,S) as MAC(K, S|"relay").
- Define M_receive(K,S) as MAC(K, S|"receive").
- Define Z(n) as a series of n [00] bytes.
- Define BODY_LEN as 509
- The cell message format is now:
- Relay command [1 byte]
- StreamID [2 bytes]
- Length [2 bytes]
- Data [variable bytes]
- Helper function: CHECK(Cell [in], b [in], K [in], S [in,out]):
- Let M = Cell[0:b]
- Let Rest = Cell[b:...]
- If b == 0:
- Return (nil, Rest)
- Let S' = S | Rest
- If M == M_relay(K,S')[0:b]:
- Set S = S'
- Return ("relay", Rest)
- If M == M_receive(K,S')[0:b]:
- Set S = S'
- Return ("receive", Rest)
- Return ("BAD", nil)
- HELPER_FUNCTION: ENCRYPT(Cell [in,out], Key [in], Ctr [in,out])
- 1. Encrypt Cell's contents using AES128_CTR, with key 'Key' and
- counter 'Ctr'. Increment 'Ctr' by the length of the cell.
- HELPER_FUNCTION: DECRYPT(Cell [in,out], Key [in], Ctr [in,out])
- 1. Same as ENCRYPT.
- Router operation, upon receiving an inbound cell:
- 1. ENCRYPT(cell, Kb, Cb)
- 2. Send the decrypted contents towards the client.
- Router operation, upon receiving an outbound cell:
- 1. Let Status, Msg = CHECK(Cell, bf, Mf, Sf)
- 2. If Status == "BAD", drop the cell and destroy the circuit.
- 3. Let Cell' = Msg | Z(BODY_LEN - len(Msg))
- 4. DECRYPT(Cell', Kf, Cf) [*]
- 5. If Status == "receive" or (Status == nil and there is no
- next hop), Cell' is for us: process it.
- 6. Otherwise, send Cell' to the next node.
- Router operation, sending a cell towards the client:
- 1. Let Body = a relay cell body of BODY_LEN-bb_i bytes.
- 2. Let Cell' = ENCRYPT(Body, Kb, Cb)
- 3. Let Sb = Sb | Cell'
- 4. Let M = M_receive(Mb, Sb)[0:b]
- 5. Send the cell M | Cell' back towards the client.
- Client operation, upon receiving an inbound cell:
- For each hop H in the circuit, from first to last:
- 1. Let Status, Msg = CHECK(Cell, bb_i, Mb_i, Sb_i)
- 2. If Status = "relay", drop the cell and destroy
- the circuit. (BAD is okay; it means that this hop didn't
- originate the cell.)
- 3. DECRYPT(Msg, Kb_i, Cb_i)
- 4. If Status = "receive", this cell is from hop i; process
- it.
- 5. Otherwise, set Cell = Msg.
- Client operation, sending an outbound cell:
- Let BF = the total of all bf_i values.
- 1. Construct a relay cell body Msg of BODY_LEN-BF bytes.
- 2. For each hop i, let Stream_i = ENCRYPT(Kf_i,Z(CELL_LEN),Cf_i)
- 3. Let Pad_0 = "".
- 4. For i in range 1..N, where N is the number of hops:
- Let Pad_i = Pad_{i-1} | Z(bf_i)
- Let S_last = the last len(Pad_i) bytes of Stream_i.
- Let Pad_i = Pad_i xor S_last
- Now Pad_i is the padding as it will stand after node i
- has processed it.
- 5. For i in range N..1, where N is the number of hops:
- If this is the last hop, let M_* = M_receive. Else let
- M_* = M_relay.
- Let Body = Msg xor the first len(Msg) bytes of Stream_i
- Let M = M_*(Mf, Body | Pad_(i-1))
- Set Msg = M[:bf_i] | Body
- 6. Send Msg outbound to the first relay in the circuit.
- [*] Strictly speaking, we could omit the pad-and-decrypt
- operation once we know we're the final hop.
- R. References
- [Prop188] Tor Proposal 188: Bridge Guards and other anti-enumeration defenses
- https://gitweb.torproject.org/torspec.git/blob/HEAD:/proposals/188-bridge-guards.txt
- [TorSpec] The Tor Protocol Specification
- https://gitweb.torproject.org/torspec.git?a=blob_plain;hb=HEAD;f=tor-spec.txt
- [TorDesign] Dingledine et al, "Tor: The Second Generation Onion
- Router",
- https://svn.torproject.org/svn/projects/design-paper/tor-design.pdf
- [Tweak] Liskov et al, "Tweakable Block Ciphers",
- http://www.cs.berkeley.edu/~daw/papers/tweak-crypto02.pdf
- [XF] Xinwen Fu et al, "One Cell is Enough to Break Tor's Anonymity"
- [23R] The 23 Raccoons, "Analysis of the Relative Severity of Tagging
- Attacks" http://archives.seul.org/or/dev/Mar-2012/msg00019.html
- (You'll want to read the rest of the thread too.)
|