aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--.gitlab-ci.yml14
-rw-r--r--README.md33
-rwxr-xr-xbin/check_links40
-rwxr-xr-xbin/make_redirects12
-rw-r--r--spec/README.md110
-rw-r--r--spec/STYLE.md56
-rw-r--r--spec/SUMMARY.md16
-rw-r--r--spec/back-matter.md68
-rw-r--r--spec/overview.md140
-rw-r--r--spec/param-spec.md2
-rw-r--r--spec/permalinks.md57
-rw-r--r--spec/tor-spec/cell-packet-format.md16
-rw-r--r--spec/tor-spec/channels.md309
-rw-r--r--spec/tor-spec/closing-streams.md2
-rw-r--r--spec/tor-spec/create-created-cells.md489
-rw-r--r--spec/tor-spec/creating-circuits.md73
-rw-r--r--spec/tor-spec/negotiating-channels.md529
-rw-r--r--spec/tor-spec/obsolete-channels.md168
-rw-r--r--spec/tor-spec/opening-streams.md6
-rw-r--r--spec/tor-spec/preliminaries.md6
-rw-r--r--spec/tor-spec/relay-cells.md122
-rw-r--r--spec/tor-spec/relay-keys.md161
-rw-r--r--spec/tor-spec/routing-relay-cells.md30
-rw-r--r--spec/tor-spec/setting-circuit-keys.md4
-rw-r--r--spec/tor-spec/subprotocol-versioning.md269
-rw-r--r--spec/tor-spec/system-overview.md61
27 files changed, 1612 insertions, 1184 deletions
diff --git a/.gitignore b/.gitignore
index dc6ea07..2f9bd0f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,6 @@
# mdbook outputs
/html
+
+# bin/check_links output
+/html.link-check
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 1b82c3c..bb2dec4 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -17,6 +17,20 @@ build:
paths:
- cache
+link-check:
+ image: rust:bookworm
+ script:
+ - ./bin/via-cargo-install-in-ci mdbook
+ - apt-get update && apt-get install -y git python3 python3-yaml linklint
+ - ./bin/build_html
+ - ./bin/check_links
+ artifacts:
+ paths:
+ - html.link-check
+ cache:
+ paths:
+ - cache
+
include:
project: tpo/tpa/ci-templates
file:
diff --git a/README.md b/README.md
index 95d0fe8..2581c8f 100644
--- a/README.md
+++ b/README.md
@@ -1,31 +1,12 @@
# Tor specification repository
-**IF YOU WANT TO READ THESE SPECS,
-[GO HERE](https://tpo.pages.torproject.net/core/torspec/).** (It is a temporoary location; we intend to move it to `spec.torproject.org`.
+This is the source code of the Tor specification documents.
-This is the central location for editing and maintaining the Tor
-specifications and proposals for feature changes.
+**To read the Tor Specifications online**,
+please go to the canonical site <https://spec.torproject.org/>.
-The specification is rendered at
-[better-url-here](https://tpo.pages.torproject.net/core/torspec/);
-if you want to _read_ the specifications, that is the place to start.
+Overview of the source code layout, and build instructions,
+are in `spec/back-matter.md`.
-The official site for this repository is on
-[gitlab.torproject.org](https://gitlab.torproject.org/tpo/core/torspec/)
-
-We use mdBook to convert these specifications into the webpages you see above.
-For more information about editing them, start with the
-[mdBook manual]([mdBook]((https://rust-lang.github.io/mdBook/)).
-
-The core of this repository is:
- * `spec` — A set of markdown files which contain the specifications.
- The file `src/SUMAMRY.md` controls their ordering within the
- rendered specification.
- * `proposals` — A directory of change proposals for the Tor protocols.
-
-Additionally, this repository contains:
- * `mdbook` — A configuration file controlling how the specifications
- are rendered.
- * `attic` — Obsolete specifications describing no-longer-in-use
- pieces of the Tor specification, and obsolete formats of the
- existing specifications.
+The canonical source repository is on the Tor Project's gitab, at
+<https://gitlab.torproject.org/tpo/core/torspec/>
diff --git a/bin/check_links b/bin/check_links
new file mode 100755
index 0000000..890ac30
--- /dev/null
+++ b/bin/check_links
@@ -0,0 +1,40 @@
+#!/bin/bash
+#
+# Check rustdoc HTML links and anchors
+# bin/build_html must have been run first.
+#
+# Adapted from
+# https://gitlab.torproject.org/Diziet/rust-derive-adhoc/-/blob/main/maint/check-doc-links?ref_type=heads
+
+set -e
+set -o pipefail
+
+# nailing-cargo --no-nail --- bin/build_html
+# nailing-cargo --preclean=no --- bin/check_links
+
+chk_dir=html.link-check
+
+rm -rf html.link-check
+cp -al html $chk_dir
+
+# Fix up https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=425632
+
+find $chk_dir -name \*.html -print0 |
+xargs -0r -- perl -i~ -pe '
+ s{\bid=("[^"]+")[^<>]*\>}{$&<a name=$1>}g;
+'
+
+linklint -out linklint.errors -error -root $chk_dir /
+
+cat linklint.errors
+
+set +e
+grep ERROR linklint.errors
+rc=$?
+set -e
+
+case $rc in
+0) echo >&2 '** found linkcheck errors **'; exit 1;;
+1) ;;
+*) echo >&2 "linkcheck failed $rc"; exit 1;;
+esac
diff --git a/bin/make_redirects b/bin/make_redirects
index ea8ea3b..a26b871 100755
--- a/bin/make_redirects
+++ b/bin/make_redirects
@@ -16,8 +16,8 @@ def update_file(fname, start_marker, end_marker, replacement):
BOOK_START = "# BEGIN AUTO-GENERATED REDIRECTS\n"
BOOK_END = "# END AUTO-GENERATED REDIRECTS\n"
-README_START = "<!-- BEGIN AUTO-GENERATED REDIRECTS -->\n"
-README_END = "<!-- END AUTO-GENERATED REDIRECTS -->\n"
+HTML_MARKER_START = "<!-- BEGIN AUTO-GENERATED REDIRECTS -->\n"
+HTML_MARKER_END = "<!-- END AUTO-GENERATED REDIRECTS -->\n"
def book_redirects(rs, spec_dir):
lines = []
@@ -38,12 +38,12 @@ def book_redirects(rs, spec_dir):
)
return "".join(lines)
-def readme_redirects(rs):
+def permalinks_redirects(rs):
lines = [ "<dl>\n" ]
for kwd, info in rs.items():
target = info['target']
desc = info['description']
- lines.append(f'<dt><a href="/{kwd}"><code>/{kwd}</code></a></dt>\n')
+ lines.append(f'<dt><code>/{kwd}</code></dt>\n')
lines.append(f'<dd><a href="{target}"><code>{target}</code> ({desc})</a></dt>\n')
lines.append("</dl>\n")
@@ -66,7 +66,7 @@ if __name__ == '__main__':
toplevel = os.path.join(os.path.dirname(sys.argv[0]), "..")
spec_book_fname = os.path.join(toplevel, "mdbook", "spec", "book.toml")
spec_dir = os.path.join(toplevel, "spec")
- readme_fname = os.path.join(toplevel, "spec", "README.md")
+ permalinks_fname = os.path.join(toplevel, "spec", "permalinks.md")
prop_dir = os.path.join(toplevel, "proposals")
prop_book_fname = os.path.join(toplevel, "mdbook", "proposals", "book.toml")
yaml_fname = os.path.join(toplevel, "mdbook", "spec", "spec-redirects.yaml")
@@ -74,5 +74,5 @@ if __name__ == '__main__':
rs = yaml.load(open(yaml_fname), yaml.Loader)['redirects']
update_file(spec_book_fname, BOOK_START, BOOK_END, book_redirects(rs, spec_dir))
- update_file(readme_fname, README_START, README_END, readme_redirects(rs))
+ update_file(permalinks_fname, HTML_MARKER_START, HTML_MARKER_END, permalinks_redirects(rs))
update_file(prop_book_fname, BOOK_START, BOOK_END, proposal_redirects(prop_dir))
diff --git a/spec/README.md b/spec/README.md
index 6d1dfeb..920486d 100644
--- a/spec/README.md
+++ b/spec/README.md
@@ -36,118 +36,8 @@ tor protocol specification](./tor-spec), which describes how our
protocol works. After that, you should be able to jump around to
the topics that interest you most. The introduction of each top-level
chapter should provide an introduction.
-
-## How to edit these specifications
-
-These specifications are displayed using a tool called
-[`mdbook`](https://rust-lang.github.io/mdBook/); we recommend reading
-its documentation.
-
-To edit these specs, clone the [git repository] and edit the
-appropriate file in the [`spec` directory]. These files will match
-the URLs of their corresponding pages, so if you want to edit
-[`tor-spec/flow-control.html`](./tor-spec/flow-control),
-you'll be looking for a file
-called [`spec/tor-spec/flow-control.md`].
-
-The chapter structure as a whole is defined in a special file called
-[`SUMMARY.md`]. Its format is pretty restrictive; see the [mdbook
-documentation][mdbook documentation] for more information.
-
-You can build the website locally to see how it renders. To do this,
-just install mdbook and run the `./bin/build_html` script. (You will
-need to have mdbook installed to do this.)
-
-We have started a [style guide](./STYLE.md) for writing new parts of
-this spec; as of 2023 it is quite preliminary. You should feel free to
-edit it!
-
-### Managing links
-
-We're in the early stages of this spec organization, but we should
-still be thinking about long term maintainability.
-
-Please think about how to keep links working in the long term.
-If you are going to add a link to a file, make sure that the file's
-name is reasonable. Before you rename a file, consider adding
-a redirect from the file's old name. (See the mdbook documentation
-for more information about how.)
-
-If you want to link to a specific section within a file,
-make sure that the section has a defined anchor that makes sense.
-The syntax to define [heading ids] in mdbook looks like this:
-
-`## Heading with a long title that you want shorter name for { #shortname }`
-
-If you need to change a heading, make sure that you keep its
-`id` the same as it was before, so that links will still work.
-
-Finally, when you're looking for specific sections (e.g., to fix
-references that say "See section 5.2.3") you can look for the HTML
-anchors that our conversion process added. For example,
-if you want to find `dir-spec.txt` section 2.1.3, look for
-the anchor that says `<a id="dir-spec.txt-2.1.3"></a>`.
-
______________________________________________________________________
-## Permalinks
-
-Additionally, these URLs at `spec.toprorject.org` are intended to be
-long-term permalinks.
-
-<!-- BEGIN AUTO-GENERATED REDIRECTS -->
-<dl>
-<dt><a href="/address-spec"><code>/address-spec</code></a></dt>
-<dd><a href="https://spec.torproject.org/address-spec"><code>https://spec.torproject.org/address-spec</code> (Special Hostnames in Tor)</a></dt>
-<dt><a href="/bandwidth-file-spec"><code>/bandwidth-file-spec</code></a></dt>
-<dd><a href="https://spec.torproject.org/bandwidth-file-spec"><code>https://spec.torproject.org/bandwidth-file-spec</code> (Directory Authority Bandwidth File spec)</a></dt>
-<dt><a href="/bridgedb-spec"><code>/bridgedb-spec</code></a></dt>
-<dd><a href="https://spec.torproject.org/bridgedb-spec"><code>https://spec.torproject.org/bridgedb-spec</code> (BridgeDB specification)</a></dt>
-<dt><a href="/cert-spec"><code>/cert-spec</code></a></dt>
-<dd><a href="https://spec.torproject.org/cert-spec"><code>https://spec.torproject.org/cert-spec</code> (Ed25519 certificates in Tor)</a></dt>
-<dt><a href="/collector-protocol"><code>/collector-protocol</code></a></dt>
-<dd><a href="https://gitlab.torproject.org/tpo/network-health/metrics/collector/-/blob/master/src/main/resources/docs/PROTOCOL?ref_type=heads"><code>https://gitlab.torproject.org/tpo/network-health/metrics/collector/-/blob/master/src/main/resources/docs/PROTOCOL?ref_type=heads</code> (Protocol of CollecTor's File Structure)</a></dt>
-<dt><a href="/control-spec"><code>/control-spec</code></a></dt>
-<dd><a href="https://spec.torproject.org/control-spec"><code>https://spec.torproject.org/control-spec</code> (Tor control protocol, version 1)</a></dt>
-<dt><a href="/dir-spec"><code>/dir-spec</code></a></dt>
-<dd><a href="https://spec.torproject.org/dir-spec"><code>https://spec.torproject.org/dir-spec</code> (Tor directory protocol, version 3)</a></dt>
-<dt><a href="/dir-list-spec"><code>/dir-list-spec</code></a></dt>
-<dd><a href="https://spec.torproject.org/dir-list-spec"><code>https://spec.torproject.org/dir-list-spec</code> (Tor Directory List file format)</a></dt>
-<dt><a href="/ext-orport-spec"><code>/ext-orport-spec</code></a></dt>
-<dd><a href="https://spec.torproject.org/ext-orport-spec"><code>https://spec.torproject.org/ext-orport-spec</code> (Extended ORPort for pluggable transports)</a></dt>
-<dt><a href="/gettor-spec"><code>/gettor-spec</code></a></dt>
-<dd><a href="https://gitlab.torproject.org/tpo/core/torspec/-/raw/main/attic/text_formats/gettor-spec.txt?ref_type=heads"><code>https://gitlab.torproject.org/tpo/core/torspec/-/raw/main/attic/text_formats/gettor-spec.txt?ref_type=heads</code> (GetTor specification)</a></dt>
-<dt><a href="/padding-spec"><code>/padding-spec</code></a></dt>
-<dd><a href="https://spec.torproject.org/padding-spec"><code>https://spec.torproject.org/padding-spec</code> (Tor Padding Specification)</a></dt>
-<dt><a href="/path-spec"><code>/path-spec</code></a></dt>
-<dd><a href="https://spec.torproject.org/path-spec"><code>https://spec.torproject.org/path-spec</code> (Tor Path Specification)</a></dt>
-<dt><a href="/pt-spec"><code>/pt-spec</code></a></dt>
-<dd><a href="https://spec.torproject.org/pt-spec"><code>https://spec.torproject.org/pt-spec</code> (Tor Pluggable Transport Specification, version 1)</a></dt>
-<dt><a href="/rend-spec"><code>/rend-spec</code></a></dt>
-<dd><a href="https://spec.torproject.org/rend-spec"><code>https://spec.torproject.org/rend-spec</code> (Tor Onion Service Rendezvous Specification, latest version)</a></dt>
-<dt><a href="/rend-spec-v2"><code>/rend-spec-v2</code></a></dt>
-<dd><a href="https://gitlab.torproject.org/tpo/core/torspec/-/blob/main/attic/rend-spec-v2.txt?ref_type=heads"><code>https://gitlab.torproject.org/tpo/core/torspec/-/blob/main/attic/rend-spec-v2.txt?ref_type=heads</code> (Tor Onion Service Rendezvous Specification, Version 2 (Obsolete))</a></dt>
-<dt><a href="/rend-spec-v3"><code>/rend-spec-v3</code></a></dt>
-<dd><a href="https://spec.torproject.org/rend-spec"><code>https://spec.torproject.org/rend-spec</code> (Tor Onion Service Rendezvous Specification, Version 3 (Latest))</a></dt>
-<dt><a href="/socks-extensions"><code>/socks-extensions</code></a></dt>
-<dd><a href="https://spec.torproject.org/socks-extensions"><code>https://spec.torproject.org/socks-extensions</code> (Tor's extensions to the SOCKS protocol)</a></dt>
-<dt><a href="/srv-spec"><code>/srv-spec</code></a></dt>
-<dd><a href="https://spec.torproject.org/srv-spec"><code>https://spec.torproject.org/srv-spec</code> (Tor Shared Random Subsystem Specification)</a></dt>
-<dt><a href="/tor-fw-helper-spec"><code>/tor-fw-helper-spec</code></a></dt>
-<dd><a href="https://gitlab.torproject.org/tpo/core/torspec/-/blob/main/attic/tor-fw-helper-spec.txt?ref_type=heads"><code>https://gitlab.torproject.org/tpo/core/torspec/-/blob/main/attic/tor-fw-helper-spec.txt?ref_type=heads</code> (Tor's (little) Firewall Helper specification)</a></dt>
-<dt><a href="/tor-spec"><code>/tor-spec</code></a></dt>
-<dd><a href="https://spec.torproject.org/tor-spec"><code>https://spec.torproject.org/tor-spec</code> (Tor Protocol Specification)</a></dt>
-<dt><a href="/torbrowser-design"><code>/torbrowser-design</code></a></dt>
-<dd><a href="https://2019.www.torproject.org/projects/torbrowser/design/"><code>https://2019.www.torproject.org/projects/torbrowser/design/</code> (The Design and Implementation of the Tor Browser)</a></dt>
-<dt><a href="/version-spec"><code>/version-spec</code></a></dt>
-<dd><a href="https://spec.torproject.org/version-spec"><code>https://spec.torproject.org/version-spec</code> (How Tor Version Numbers Work)</a></dt>
-<dt><a href="/tor-design"><code>/tor-design</code></a></dt>
-<dd><a href="https://svn.torproject.org/svn/projects/design-paper/tor-design.pdf"><code>https://svn.torproject.org/svn/projects/design-paper/tor-design.pdf</code> (Tor: The Second-Generation Onion Router)</a></dt>
-<dt><a href="/walking-onions"><code>/walking-onions</code></a></dt>
-<dd><a href="https://spec.torproject.org/proposals/323-walking-onions-full.html"><code>https://spec.torproject.org/proposals/323-walking-onions-full.html</code> (Walking Onions specifications)</a></dt>
-</dl>
-<!-- END AUTO-GENERATED REDIRECTS -->
-
[git repository]: https://gitlab.torproject.org/tpo/core/torspec/
[heading ids]: https://github.com/raphlinus/pulldown-cmark/blob/master/specs/heading_attrs.txt
[mdbook documentation]: https://rust-lang.github.io/mdBook/format/summary.html
diff --git a/spec/STYLE.md b/spec/STYLE.md
index d14f7f1..c5b5ef1 100644
--- a/spec/STYLE.md
+++ b/spec/STYLE.md
@@ -1,5 +1,27 @@
# Tor specifications: style and usage notes
+## Audience
+
+The primary intended audiences are:
+
+ * Programmers:
+ implementors of the Tor Protocols.
+ This includes both maintainers of existing implementations,
+ and people writing new implementations.
+
+ * Researchers:
+ people analysing the security of the Tor Protocols,
+ including both academic research and
+ practical security investigation.
+
+ * Expert users who wish to fully understand
+ the operation of their Tor software.
+ This includes users of clients and relays.
+
+ * Directory authority operators,
+ and others with a critical technical role
+ in the integrity of the Tor network.
+
## Scope and intentions
@@ -36,6 +58,13 @@ them upstreamed to more project-wide guides, if they are suitable.
Make sure you have read [this part of the README](https://spec.torproject.org/index.html#how-to-edit-these-specifications)!
+We are moving towards using
+[semantic newlines](https://rhodesmill.org/brandon/2012/one-sentence-per-line/):
+put each thought, or sentence, or subclause, on its own line,
+in the Markdown source text.
+(This is not yet applied consistently,
+and we won't reject contributions that don't write that way.)
+
## Vocabulary
We use these terms freely:
@@ -92,3 +121,30 @@ Neither of these is really great. We should find something better.
> normative text, it is a good idea to put it in quoted text, like
> this.
+
+## Managing links
+
+We're in the early stages of this spec organization, but we should
+still be thinking about long term maintainability.
+
+Please think about how to keep links working in the long term.
+If you are going to add a link to a file, make sure that the file's
+name is reasonable. Before you rename a file, consider adding
+a redirect from the file's old name. (See the mdbook documentation
+for more information about how.)
+
+If you want to link to a specific section within a file,
+make sure that the section has a defined anchor that makes sense.
+The syntax to define [heading ids] in mdbook looks like this:
+
+`## Heading with a long title that you want shorter name for { #shortname }`
+
+If you need to change a heading, make sure that you keep its
+`id` the same as it was before, so that links will still work.
+
+Finally, when you're looking for specific sections (e.g., to fix
+references that say "See section 5.2.3") you can look for the HTML
+anchors that our conversion process added. For example,
+if you want to find `dir-spec.txt` section 2.1.3, look for
+the anchor that says `<a id="dir-spec.txt-2.1.3"></a>`.
+
diff --git a/spec/SUMMARY.md b/spec/SUMMARY.md
index 2f06c0b..a3725c1 100644
--- a/spec/SUMMARY.md
+++ b/spec/SUMMARY.md
@@ -1,15 +1,18 @@
# Summary
-[Introduction](./README.md)
+[About these specifications](./README.md)
+[A short introduction to Tor](./overview.md)
# The core Tor protocol
- [`Tor Protocol Specification`](./tor-spec/index.md)
- [Preliminaries](./tor-spec/preliminaries.md)
- [System overview](./tor-spec/system-overview.md)
- - [Connections](./tor-spec/channels.md)
- - [Cell Packet format](./tor-spec/cell-packet-format.md)
- - [Negotiating and initializing connections](./tor-spec/negotiating-channels.md)
+ - [Relay keys and identities](./tor-spec/relay-keys.md)
+ - [Channels](./tor-spec/channels.md)
+ - [Negotiating and initializing channels](./tor-spec/negotiating-channels.md)
+ - [Obsolete channel negotiation handshakes](./tor-spec/obsolete-channels.md)
+ - [Cells (messages on channels)](./tor-spec/cell-packet-format.md)
- [Circuit management](./tor-spec/circuit-management.md)
- [CREATE and CREATED cells](./tor-spec/create-created-cells.md)
- [Setting circuit keys](./tor-spec/setting-circuit-keys.md)
@@ -174,4 +177,9 @@
# Unfinished
- [`Glossary`](./glossary.md)
+
+# Maintenance and and editing of the Tor Specifications
+
+- [`About the Tor Specifications documents`](./back-matter.md)
- [`Style guide`](./STYLE.md)
+- [`Permalinks`](./permalinks.md)
diff --git a/spec/back-matter.md b/spec/back-matter.md
new file mode 100644
index 0000000..6a50633
--- /dev/null
+++ b/spec/back-matter.md
@@ -0,0 +1,68 @@
+# About the Tor Specifications documents
+
+The canonical, official, versions of these documents are on the
+[Tor Specifications website](https://spec.torproject.org/)
+maintained by the [Tor Project](https://www.torproject.org/).
+
+Only the Tor Specifications themselves are approved.
+The [Proposals](../proposals/) are, by their nature, drafts.
+
+When linking to the Specifications,
+consider using one of the links advertised in the
+[Table of Permalinks](permalinks.html).
+
+## Source code
+
+The Specifications and Proposals are maintained by the Tor Project
+in a
+[gitlab repository](https://gitlab.torproject.org/tpo/core/torspec/).
+
+Corrections and clarifications are welcome.
+To propose a change to the Tor protocol, use the
+[Proposals process](proposals/001-process.txt)
+
+## Building
+
+The documents are in Markdown and formatted with
+[mdbook](https://rust-lang.github.io/mdBook/).
+To build the formatted HTML:
+
+```text,ignore
+cargo install mdbook
+git clone https://gitlab.torproject.org/tpo/core/torspec/
+cd torspec
+bin/build_html
+```
+
+The output is then in `html/`.
+
+## Source code structure, and output webtree
+
+There are two mdbook books here:
+
+ * **The Tor Specifications**: source code in `specs/`,
+ formatted output in `html/`.
+
+ * **Proposals**: source code in `proposals/`,
+ formatted output in `html/proposals/`.
+
+Each book's source files are listed,
+and the chapter defined,
+in its `SUMMARY.md`.
+The format is pretty restrictive;
+see the
+[mdbook documentation](https://rust-lang.github.io/mdBook/format/summary.html).
+
+## Editing advice
+
+To edit these specs, clone the [git repository] and edit the
+appropriate file in the [`spec` directory]. These files will match
+the URLs of their corresponding pages, so if you want to edit
+[`tor-spec/flow-control.html`],
+you'll be looking for a file
+called [`spec/tor-spec/flow-control.md`].
+
+We have started a [style guide](./STYLE.md) for writing new parts of
+this spec; as of 2023 it is quite preliminary. You should feel free to
+edit it!
+
diff --git a/spec/overview.md b/spec/overview.md
new file mode 100644
index 0000000..f6f3d5d
--- /dev/null
+++ b/spec/overview.md
@@ -0,0 +1,140 @@
+# A short introduction to Tor {#tor-intro}
+
+### Basic functionality {#basics}
+
+Tor is a distributed overlay network designed to anonymize
+low-latency TCP-based applications
+such as web browsing, secure shell, and instant messaging.
+The network is built of a number of servers, called **relays**
+(also called "onion routers" or "ORs" in some older documentation).
+
+To connect to the network,
+a client needs to download an up-to-date signed directory
+of the relays on the network.
+These directory documents are generated and signed
+by a set of semi-trusted **directory authority** servers,
+and are cached by the relays themselves.
+(If a client does not yet have a directory,
+it finds a cache by looking at a list of stable cache locations,
+distributed along with its source code.)
+
+> For more information on the directory subsystem,
+> see the [directory protocol specification](./dir-spec).
+
+After the client knows the relays on the network,
+it can pick a relay and open a [**channel**](./tor-spec/channels.md)
+to one of these relays.
+A channel is an encrypted reliable non-anonymous transport
+between a client and a relay or a relay and a relay,
+used to transmit messages called [**cells**](./tor-spec/cell-packet-format.md).
+(Under the hood, a channel is just a TLS connection over TCP,
+with a specified encoding for cells.)
+
+To anonymize its traffic,
+a client chooses a **path**—a sequence of relays on the network—
+and opens a channel to the first relay on the path
+(if it does not already have a channel open to that relay).
+The client then uses that channel to build
+a multi-hop cryptographic structure
+called a [**circuit**](./tor-spec/circuit-management.md).
+A circuit is built over a sequence of relays (typically three).
+Every relay in the circuit knows its precessor and successor,
+but no other relays in the circuit.
+Many circuits can be multiplexed over a single channel.
+
+> For more information on how paths are selected,
+> see the [path specification](./path-spec).
+> The first hop on a path,
+> also called a **guard node**,
+> has complicated rules for its selection;
+> for more on those, see the [guard specification](./guard-spec).
+
+Once a circuit exists,
+the client can use it to exchange fixed-length
+[**relay cells**](./tor-spec/relay-cells.md)
+with any relay on the circuit.
+These relay cells are wrapped in multiple layers of encryption:
+as part of building the circuit,
+the client [negotiates](./tor-spec/create-created-cells.md)
+a separate set of symmetric keys
+with each relay on the circuit.
+Each relay removes (or adds)
+a [single layer of encryption](./tor-spec/routing-relay-cells.md)
+for each relay cell before passing it on.
+
+A client uses these relay cells
+to exchange [**relay messages**](./tor-spec/relay-cells.md) with relays on a circuit.
+These "relay messages" in turn are used
+to actually deliver traffic over the network.
+In the [simplest use case](./tor-spec/opening-streams.md),
+the client sends a `BEGIN` message
+to tell the last relay on the circuit
+(called the **exit node**)
+to create a new session, or **stream**,
+and associate that stream
+with a new TCP connection to a target host.
+The exit node replies with a `CONNECTED` message
+to say that the TCP connection has succeeded.
+Then the client and the exit exchange `DATA` messages
+to represent the contents of the anonymized stream.
+
+> Note that as of 2023,
+> the specifications do not perfectly distinguish
+> between relay cells and relay messages.
+> This is because, until recently,
+> there was a 1-to-1 relationship between the two:
+> every relay cell held a single relay message.
+> As [proposal 340](proposals/340-packed-and-fragmented.md) is implemented,
+> we will revise the specifications
+> for improved clarify on this point.
+
+Other kinds of relay messages can be used
+for more advanced functionality.
+
+<!-- TODO: I'm not so sure about the vocabulary in this part. -->
+
+Using a system called **conflux**
+a client can build multiple circuits to the _same_ exit node,
+and associate those circuits within a **conflux set**.
+Once this is done,
+relay messages can be sent over _either_ circuit in the set,
+depending on capacity and performance.
+
+> For more on conflux,
+> which has been integrated into the C tor implementation,
+> but not yet (as of 2023) into this document,
+> see [proposal 329](proposals/329-traffic-splitting.txt).
+
+### Advanced topics: Onion services and responder anonymity {#onions}
+
+In addition to _initiating_ anonymous communications,
+clients can also arrange to _receive_ communications
+without revealing their identity or location.
+This is called **responder anonymity**,
+and the mechanism Tor uses to achieve it
+is called **onion services**
+(or "hidden services" or "rendezvous services"
+in some older documentation).
+
+> For the details on onion services,
+> see the [Tor Rendezvous Specification](./rend-spec).
+
+### Advanced topics: Censorship resistence {#anticensorship}
+
+In some places, Tor is censored.
+Typically, censors do this by blocking connections
+to the addresses of the known Tor relays,
+and by blocking traffic that resembles Tor.
+
+To resist this censorship,
+some Tor relays, called **bridges**,
+are unlisted in the public directory:
+their addresses are distributed by [other means](./bridgedb-spec.md).
+(To distinguish ordinary published relays from bridges,
+we sometimes call them **public relays**.)
+
+Additionally, Tor clients and bridges can use extension programs,
+called [**pluggable transports**](./pt-spec),
+that obfuscate their traffic to make it harder to detect.
+
+
diff --git a/spec/param-spec.md b/spec/param-spec.md
index 2f79120..f74319c 100644
--- a/spec/param-spec.md
+++ b/spec/param-spec.md
@@ -187,6 +187,8 @@ people to use them as one-hop proxies. See trac entry 1751 for details.
Min: 0, Max: 1
First-appeared: 0.2.2.17-alpha
+<a id="onion-key-rotation-days"></a>
+
"onion-key-rotation-days" -- (min 1, max 90, default 28)
"onion-key-grace-period-days" -- (min 1, max
diff --git a/spec/permalinks.md b/spec/permalinks.md
new file mode 100644
index 0000000..052d48f
--- /dev/null
+++ b/spec/permalinks.md
@@ -0,0 +1,57 @@
+# Permalinks
+
+These URLs at `spec.toprorject.org` are intended to be
+long-term permalinks.
+
+<!-- BEGIN AUTO-GENERATED REDIRECTS -->
+<dl>
+<dt><code>/address-spec</code></dt>
+<dd><a href="https://spec.torproject.org/address-spec"><code>https://spec.torproject.org/address-spec</code> (Special Hostnames in Tor)</a></dt>
+<dt><code>/bandwidth-file-spec</code></dt>
+<dd><a href="https://spec.torproject.org/bandwidth-file-spec"><code>https://spec.torproject.org/bandwidth-file-spec</code> (Directory Authority Bandwidth File spec)</a></dt>
+<dt><code>/bridgedb-spec</code></dt>
+<dd><a href="https://spec.torproject.org/bridgedb-spec"><code>https://spec.torproject.org/bridgedb-spec</code> (BridgeDB specification)</a></dt>
+<dt><code>/cert-spec</code></dt>
+<dd><a href="https://spec.torproject.org/cert-spec"><code>https://spec.torproject.org/cert-spec</code> (Ed25519 certificates in Tor)</a></dt>
+<dt><code>/collector-protocol</code></dt>
+<dd><a href="https://gitlab.torproject.org/tpo/network-health/metrics/collector/-/blob/master/src/main/resources/docs/PROTOCOL?ref_type=heads"><code>https://gitlab.torproject.org/tpo/network-health/metrics/collector/-/blob/master/src/main/resources/docs/PROTOCOL?ref_type=heads</code> (Protocol of CollecTor's File Structure)</a></dt>
+<dt><code>/control-spec</code></dt>
+<dd><a href="https://spec.torproject.org/control-spec"><code>https://spec.torproject.org/control-spec</code> (Tor control protocol, version 1)</a></dt>
+<dt><code>/dir-spec</code></dt>
+<dd><a href="https://spec.torproject.org/dir-spec"><code>https://spec.torproject.org/dir-spec</code> (Tor directory protocol, version 3)</a></dt>
+<dt><code>/dir-list-spec</code></dt>
+<dd><a href="https://spec.torproject.org/dir-list-spec"><code>https://spec.torproject.org/dir-list-spec</code> (Tor Directory List file format)</a></dt>
+<dt><code>/ext-orport-spec</code></dt>
+<dd><a href="https://spec.torproject.org/ext-orport-spec"><code>https://spec.torproject.org/ext-orport-spec</code> (Extended ORPort for pluggable transports)</a></dt>
+<dt><code>/gettor-spec</code></dt>
+<dd><a href="https://gitlab.torproject.org/tpo/core/torspec/-/raw/main/attic/text_formats/gettor-spec.txt?ref_type=heads"><code>https://gitlab.torproject.org/tpo/core/torspec/-/raw/main/attic/text_formats/gettor-spec.txt?ref_type=heads</code> (GetTor specification)</a></dt>
+<dt><code>/padding-spec</code></dt>
+<dd><a href="https://spec.torproject.org/padding-spec"><code>https://spec.torproject.org/padding-spec</code> (Tor Padding Specification)</a></dt>
+<dt><code>/path-spec</code></dt>
+<dd><a href="https://spec.torproject.org/path-spec"><code>https://spec.torproject.org/path-spec</code> (Tor Path Specification)</a></dt>
+<dt><code>/pt-spec</code></dt>
+<dd><a href="https://spec.torproject.org/pt-spec"><code>https://spec.torproject.org/pt-spec</code> (Tor Pluggable Transport Specification, version 1)</a></dt>
+<dt><code>/rend-spec</code></dt>
+<dd><a href="https://spec.torproject.org/rend-spec"><code>https://spec.torproject.org/rend-spec</code> (Tor Onion Service Rendezvous Specification, latest version)</a></dt>
+<dt><code>/rend-spec-v2</code></dt>
+<dd><a href="https://gitlab.torproject.org/tpo/core/torspec/-/blob/main/attic/rend-spec-v2.txt?ref_type=heads"><code>https://gitlab.torproject.org/tpo/core/torspec/-/blob/main/attic/rend-spec-v2.txt?ref_type=heads</code> (Tor Onion Service Rendezvous Specification, Version 2 (Obsolete))</a></dt>
+<dt><code>/rend-spec-v3</code></dt>
+<dd><a href="https://spec.torproject.org/rend-spec"><code>https://spec.torproject.org/rend-spec</code> (Tor Onion Service Rendezvous Specification, Version 3 (Latest))</a></dt>
+<dt><code>/socks-extensions</code></dt>
+<dd><a href="https://spec.torproject.org/socks-extensions"><code>https://spec.torproject.org/socks-extensions</code> (Tor's extensions to the SOCKS protocol)</a></dt>
+<dt><code>/srv-spec</code></dt>
+<dd><a href="https://spec.torproject.org/srv-spec"><code>https://spec.torproject.org/srv-spec</code> (Tor Shared Random Subsystem Specification)</a></dt>
+<dt><code>/tor-fw-helper-spec</code></dt>
+<dd><a href="https://gitlab.torproject.org/tpo/core/torspec/-/blob/main/attic/tor-fw-helper-spec.txt?ref_type=heads"><code>https://gitlab.torproject.org/tpo/core/torspec/-/blob/main/attic/tor-fw-helper-spec.txt?ref_type=heads</code> (Tor's (little) Firewall Helper specification)</a></dt>
+<dt><code>/tor-spec</code></dt>
+<dd><a href="https://spec.torproject.org/tor-spec"><code>https://spec.torproject.org/tor-spec</code> (Tor Protocol Specification)</a></dt>
+<dt><code>/torbrowser-design</code></dt>
+<dd><a href="https://2019.www.torproject.org/projects/torbrowser/design/"><code>https://2019.www.torproject.org/projects/torbrowser/design/</code> (The Design and Implementation of the Tor Browser)</a></dt>
+<dt><code>/version-spec</code></dt>
+<dd><a href="https://spec.torproject.org/version-spec"><code>https://spec.torproject.org/version-spec</code> (How Tor Version Numbers Work)</a></dt>
+<dt><code>/tor-design</code></dt>
+<dd><a href="https://svn.torproject.org/svn/projects/design-paper/tor-design.pdf"><code>https://svn.torproject.org/svn/projects/design-paper/tor-design.pdf</code> (Tor: The Second-Generation Onion Router)</a></dt>
+<dt><code>/walking-onions</code></dt>
+<dd><a href="https://spec.torproject.org/proposals/323-walking-onions-full.html"><code>https://spec.torproject.org/proposals/323-walking-onions-full.html</code> (Walking Onions specifications)</a></dt>
+</dl>
+<!-- END AUTO-GENERATED REDIRECTS -->
diff --git a/spec/tor-spec/cell-packet-format.md b/spec/tor-spec/cell-packet-format.md
index b0533dd..7251db0 100644
--- a/spec/tor-spec/cell-packet-format.md
+++ b/spec/tor-spec/cell-packet-format.md
@@ -1,9 +1,19 @@
<a id="tor-spec.txt-3"></a>
-# Cell Packet format{#cell-packet-format}
+# Cells (messages on channels) {#cell-packet-format}
The basic unit of communication for onion routers and onion
-proxies is a fixed-width "cell".
+proxies is a "cell".
+
+Once a TLS connection is established, the two sides send cells
+to one another. Cells are sent serially. Standard
+cells are CELL_LEN(link_proto) bytes long, but variable-length cells
+also exist.
+
+Cells may be sent embedded in TLS records
+of any size or divided across TLS records, but the framing of TLS
+records MUST NOT leak information about the type or contents of the
+cells.
On a version 1 connection, each cell contains the following
fields:
@@ -117,4 +127,4 @@ manage circuits; see [Circuit management](./circuit-management.md#circuit-manage
`VERSIONS` and `NETINFO` cells are used to set up connections in link
protocols v2 and higher; in link protocol v3 and higher, `CERTS`,
-`AUTH_CHALLENGE`, and `AUTHENTICATE` may also be used. See [Negotiating and initializing connections](./negotiating-channels.md#negotiating-and-initializing-connections).
+`AUTH_CHALLENGE`, and `AUTHENTICATE` may also be used. See [Negotiating and initializing channels](./negotiating-channels.md#negotiating).
diff --git a/spec/tor-spec/channels.md b/spec/tor-spec/channels.md
index 60b871d..5b0020a 100644
--- a/spec/tor-spec/channels.md
+++ b/spec/tor-spec/channels.md
@@ -1,232 +1,87 @@
<a id="tor-spec.txt-2"></a>
-# Connections{#connections}
-
-Connections between two Tor relays, or between a client and a relay,
-use TLS/SSLv3 for link authentication and encryption. All
-implementations MUST support the SSLv3 ciphersuite
-"TLS_DHE_RSA_WITH_AES_128_CBC_SHA" if it is available. They SHOULD
-support better ciphersuites if available.
-
-There are three ways to perform TLS handshakes with a Tor server. In
-the first way, "certificates-up-front", both the initiator and
-responder send a two-certificate chain as part of their initial
-handshake. (This is supported in all Tor versions.) In the second
-way, "renegotiation", the responder provides a single certificate,
-and the initiator immediately performs a TLS renegotiation. (This is
-supported in Tor 0.2.0.21 and later.) And in the third way,
-"in-protocol", the initial TLS negotiation completes, and the
-parties bootstrap themselves to mutual authentication via use of the
-Tor protocol without further TLS handshaking. (This is supported in
-0.2.3.6-alpha and later.)
-
-Each of these options provides a way for the parties to learn it is
-available: a client does not need to know the version of the Tor
-server in order to connect to it properly.
-
-In "certificates up-front" (a.k.a "the v1 handshake"),
-the connection initiator always sends a
-two-certificate chain, consisting of an X.509 certificate using a
-short-term connection public key and a second, self-signed X.509
-certificate containing its identity key. The other party sends a similar
-certificate chain. The initiator's ClientHello MUST NOT include any
-ciphersuites other than:
-
-```text
- TLS_DHE_RSA_WITH_AES_256_CBC_SHA
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA
- SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
-```
-
-In "renegotiation" (a.k.a. "the v2 handshake"),
-the connection initiator sends no certificates, and
-the responder sends a single connection certificate. Once the TLS
-handshake is complete, the initiator renegotiates the handshake, with each
-party sending a two-certificate chain as in "certificates up-front".
-The initiator's ClientHello MUST include at least one ciphersuite not in
-the list above -- that's how the initiator indicates that it can
-handle this handshake. For other considerations on the initiator's
-ClientHello, see [Picking TLS ciphersuites](#picking-tls-ciphersuites}.
-
-In "in-protocol" (a.k.a. "the v3 handshake"), the initiator sends no
-certificates, and the
-responder sends a single connection certificate. The choice of
-ciphersuites must be as in a "renegotiation" handshake. There are
-additionally a set of constraints on the connection certificate,
-which the initiator can use to learn that the in-protocol handshake
-is in use. Specifically, at least one of these properties must be
-true of the certificate:
-
-```text
- * The certificate is self-signed
- * Some component other than "commonName" is set in the subject or
- issuer DN of the certificate.
- * The commonName of the subject or issuer of the certificate ends
- with a suffix other than ".net".
- * The certificate's public key modulus is longer than 1024 bits.
-```
-
-The initiator then sends a VERSIONS cell to the responder, which then
-replies with a VERSIONS cell; they have then negotiated a Tor
-protocol version. Assuming that the version they negotiate is 3 or higher
-(the only ones specified for use with this handshake right now), the
-responder sends a CERTS cell, an AUTH_CHALLENGE cell, and a NETINFO
-cell to the initiator, which may send either CERTS, AUTHENTICATE,
-NETINFO if it wants to authenticate, or just NETINFO if it does not.
-
-For backward compatibility between later handshakes and "certificates
-up-front", the ClientHello of an initiator that supports a later
-handshake MUST include at least one ciphersuite other than those listed
-above. The connection responder examines the initiator's ciphersuite list
-to see whether it includes any ciphers other than those included in the
-list above. If extra ciphers are included, the responder proceeds as in
-"renegotiation" and "in-protocol": it sends a single certificate and
-does not request
-client certificates. Otherwise (in the case that no extra ciphersuites
-are included in the ClientHello) the responder proceeds as in
-"certificates up-front": it requests client certificates, and sends a
-two-certificate chain. In either case, once the responder has sent its
-certificate or certificates, the initiator counts them. If two
-certificates have been sent, it proceeds as in "certificates up-front";
-otherwise, it proceeds as in "renegotiation" or "in-protocol".
-
-To decide whether to do "renegotiation" or "in-protocol", the
-initiator checks whether the responder's initial certificate matches
-the criteria listed above.
-
-All new relay implementations of the Tor protocol MUST support
-backwards-compatible renegotiation; clients SHOULD do this too. If
-this is not possible, new client implementations MUST support both
-"renegotiation" and "in-protocol" and use the router's
-published link protocols list (see dir-spec.txt on the "protocols" entry)
-to decide which to use.
-
-In all of the above handshake variants, certificates sent in the clear
-SHOULD NOT include any strings to identify the host as a Tor relay. In
-the "renegotiation" and "backwards-compatible renegotiation" steps, the
-initiator SHOULD choose a list of ciphersuites and TLS extensions
-to mimic one used by a popular web browser.
-
-Even though the connection protocol is identical, we will think of the
-initiator as either an onion router (OR) if it is willing to relay
-traffic for other Tor users, or an onion proxy (OP) if it only handles
-local requests. Onion proxies SHOULD NOT provide long-term-trackable
-identifiers in their handshakes.
-
-In all handshake variants, once all certificates are exchanged, all
-parties receiving certificates must confirm that the identity key is as
-expected. If the key is not as expected, the party must close the
-connection.
-
-(When initiating a connection, if a reasonably live consensus is
-available, then the expected identity key is taken from that
-consensus. But when initiating a connection otherwise, the expected
-identity key is the one given in the hard-coded authority or
-fallback list. Finally, when creating a connection because of an
-EXTEND/EXTEND2 cell, the expected identity key is the one given in
-the cell.)
-
-When connecting to an OR, all parties SHOULD reject the connection if that
-OR has a malformed or missing certificate. When accepting an incoming
-connection, an OR SHOULD NOT reject incoming connections from parties with
-malformed or missing certificates. (However, an OR should not believe
-that an incoming connection is from another OR unless the certificates
-are present and well-formed.)
-
-\[Before version 0.1.2.8-rc, ORs rejected incoming connections from ORs and
-OPs alike if their certificates were missing or malformed.\]
-
-Once a TLS connection is established, the two sides send cells
-(specified below) to one another. Cells are sent serially. Standard
-cells are CELL_LEN(link_proto) bytes long, but variable-length cells
-also exist; see [Cell Packet format](./cell-packet-format.md#cell-packet-format).
-Cells may be sent embedded in TLS records
-of any size or divided across TLS records, but the framing of TLS
-records MUST NOT leak information about the type or contents of the
-cells.
-
-TLS connections are not permanent. Either side MAY close a connection
-if there are no circuits running over it and an amount of time
-(KeepalivePeriod, defaults to 5 minutes) has passed since the last time
-any traffic was transmitted over the TLS connection. Clients SHOULD
+# Channels {#channels}
+
+A channel is a direct encrypted connection
+between two Tor relays,
+or between a client and a relay.
+
+Channels are implemented as
+[TLS](https://www.rfc-editor.org/rfc/rfc8446) sessions over TCP.
+
+Clients and relays may both open new channels;
+only a relay may be the recipient of a channel.
+
+> Historical note:
+> in some older documentation,
+> channels were sometimes called "connections".
+> This proved to be confusing,
+> and we are trying not to use the term.
+
+As part of establishing a channel,
+the responding relay will always prove cryptographic ownership
+of one or more [**relay identities**](./relay-keys.md),
+using a [handshake](./negotiating-channels.md)
+that combines TLS facilities
+and a series of Tor messages.
+The initiator MAY prove cryptographic ownership
+of their own relay identities,
+if they have any:
+public relays SHOULD prove their identities when they initiate a channel,
+whereas clients and bridges SHOULD NOT do so.
+
+Parties should usually reuse an existing channel
+rather than opening new a channel to the same relay.
+There are exceptions here;
+we discuss them more [below](#XXXX).
+
+To open a channel,
+a client or relay must know the IP address and port
+of the target relay.
+(This is sometimes called
+the "OR address" or "OR port" for the relay.)
+In most cases, the participant will also know
+one or more expected identities for the target relay,
+and will reject the channel
+if the target relay cannot cryptographically prove
+ownership of those identities.
+
+> (When initiating a connection, if a reasonably live consensus is
+> available, then the expected identity key is taken from that
+> consensus. But when initiating a connection otherwise, the expected
+> identity key is the one given in the hard-coded authority or
+> fallback list. Finally, when creating a connection because of an
+> EXTEND/EXTEND2 cell, the expected identity key is the one given in
+> the cell.)
+
+<!-- TODO: Integrate that paragraph better, or put it in a better place. -->
+
+Opening a channel is multi-step process:
+
+1. The initiator opens
+ a new TLS session with certain properties,
+ and the responding relay checks and enforces those properties.
+2. Both parties
+ exchange messages over this TLS session
+ in order to establish their identity or identities.
+3. Both parties verify that the identities that they received
+ are the ones that they expected.
+ (If any expected key is missing or not as expected,
+ the party MUST close the connection.)
+
+Once this is done, the channel is Open,
+and regular cells can be exchanged.
+
+## Channel lifetime
+
+Channels are not permanent.
+Either side MAY close a channel if there are no circuits running on it
+and an amount of time (KeepalivePeriod, defaults to 5 minutes)
+has passed since the last time any traffic was transmitted over it.
+Clients SHOULD
also hold a TLS connection with no circuits open, if it is likely that a
circuit will be built soon using that connection.
-Client-only Tor instances are encouraged to avoid using handshake
-variants that include certificates, if those certificates provide
-any persistent tags to the relays they contact. If clients do use
-certificates, they SHOULD NOT keep using the same certificates when
-their IP address changes. Clients MAY send certificates using any
-of the above handshake variants.
-
-<a id="tor-spec.txt-2.1"></a>
-
-## Picking TLS ciphersuites {#picking-tls-ciphersuites}
-
-Clients SHOULD send a ciphersuite list chosen to emulate some popular
-web browser or other program common on the internet. Clients may send
-the "Fixed Cipheruite List" below. If they do not, they MUST NOT
-advertise any ciphersuite that they cannot actually support, unless that
-cipher is one not supported by OpenSSL 1.0.1.
-
-The fixed ciphersuite list is:
-
-```text
- TLS1_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- TLS1_ECDHE_RSA_WITH_AES_256_CBC_SHA
- TLS1_DHE_RSA_WITH_AES_256_SHA
- TLS1_DHE_DSS_WITH_AES_256_SHA
- TLS1_ECDH_RSA_WITH_AES_256_CBC_SHA
- TLS1_ECDH_ECDSA_WITH_AES_256_CBC_SHA
- TLS1_RSA_WITH_AES_256_SHA
- TLS1_ECDHE_ECDSA_WITH_RC4_128_SHA
- TLS1_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- TLS1_ECDHE_RSA_WITH_RC4_128_SHA
- TLS1_ECDHE_RSA_WITH_AES_128_CBC_SHA
- TLS1_DHE_RSA_WITH_AES_128_SHA
- TLS1_DHE_DSS_WITH_AES_128_SHA
- TLS1_ECDH_RSA_WITH_RC4_128_SHA
- TLS1_ECDH_RSA_WITH_AES_128_CBC_SHA
- TLS1_ECDH_ECDSA_WITH_RC4_128_SHA
- TLS1_ECDH_ECDSA_WITH_AES_128_CBC_SHA
- SSL3_RSA_RC4_128_MD5
- SSL3_RSA_RC4_128_SHA
- TLS1_RSA_WITH_AES_128_SHA
- TLS1_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA
- TLS1_ECDHE_RSA_WITH_DES_192_CBC3_SHA
- SSL3_EDH_RSA_DES_192_CBC3_SHA
- SSL3_EDH_DSS_DES_192_CBC3_SHA
- TLS1_ECDH_RSA_WITH_DES_192_CBC3_SHA
- TLS1_ECDH_ECDSA_WITH_DES_192_CBC3_SHA
- SSL3_RSA_FIPS_WITH_3DES_EDE_CBC_SHA
- SSL3_RSA_DES_192_CBC3_SHA
- [*] The "extended renegotiation is supported" ciphersuite, 0x00ff, is
- not counted when checking the list of ciphersuites.
-```
-
-If the client sends the Fixed Ciphersuite List, the responder MUST NOT
-select any ciphersuite besides TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
-TLS_DHE_RSA_WITH_AES_128_CBC_SHA, and SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
-such ciphers might not actually be supported by the client.
-
-If the client sends a v2+ ClientHello with a list of ciphers other then
-the Fixed Ciphersuite List, the responder can trust that the client
-supports every cipher advertised in that list, so long as that ciphersuite
-is also supported by OpenSSL 1.0.1.
-
-Responders MUST NOT select any TLS ciphersuite that lacks ephemeral keys,
-or whose symmetric keys are less then KEY_LEN bits, or whose digests are
-less than HASH_LEN bits. Responders SHOULD NOT select any SSLv3
-ciphersuite other than the DHE+3DES suites listed above.
-
-<a id="tor-spec.txt-2.2"></a>
-
-## TLS security considerations
-
-Implementations MUST NOT allow TLS session resumption -- it can
-exacerbate some attacks (e.g. the "Triple Handshake" attack from
-Feb 2013), and it plays havoc with forward secrecy guarantees.
-
-Implementations SHOULD NOT allow TLS compression -- although we don't
-know a way to apply a CRIME-style attack to current Tor directly,
-it's a waste of resources.
+<!-- TODO: Give a forward-reference to explain predicted circuits
+ and how we decide that a channel is "likely" to be used. -->
+
diff --git a/spec/tor-spec/closing-streams.md b/spec/tor-spec/closing-streams.md
index 7182f48..265e9d1 100644
--- a/spec/tor-spec/closing-streams.md
+++ b/spec/tor-spec/closing-streams.md
@@ -1,6 +1,6 @@
<a id="tor-spec.txt-6.3"></a>
-# Closing streams
+# Closing streams{#closing-streams}
When an anonymized TCP connection is closed, or an edge node
encounters error on any stream, it sends a 'RELAY_END' cell along the
diff --git a/spec/tor-spec/create-created-cells.md b/spec/tor-spec/create-created-cells.md
index 453d4b0..1e6281c 100644
--- a/spec/tor-spec/create-created-cells.md
+++ b/spec/tor-spec/create-created-cells.md
@@ -55,7 +55,7 @@ or
The first format is equivalent to a CREATE2 cell with HTYPE of 'tap'
and length of `TAP_C_HANDSHAKE_LEN`. The second format is a way to
encapsulate new handshake types into the old CREATE cell format for
-migration. See 5.1.2 below. Recognized HTAG values are:
+migration. See ["EXTEND and EXTENDED cells"](#EXTEND) below. Recognized HTAG values are:
| Value | Description |
| ----- | ----------- |
@@ -69,7 +69,7 @@ The format of a CREATED cell is:
(It's equivalent to a CREATED2 cell with length of `TAP_S_HANDSHAKE_LEN`.)
-As usual with DH, x and y MUST be generated randomly.
+As usual with DH, `x` and `y` MUST be generated randomly.
In general, clients SHOULD use CREATE whenever they are using the TAP
handshake, and CREATE2 otherwise. Clients SHOULD NOT send the
@@ -125,31 +125,26 @@ RELAY_EARLY cell to the last node in the circuit.
An EXTEND2 cell's relay payload contains:
-```text
- NSPEC (Number of link specifiers) [1 byte]
- NSPEC times:
- LSTYPE (Link specifier type) [1 byte]
- LSLEN (Link specifier length) [1 byte]
- LSPEC (Link specifier) [LSLEN bytes]
- HTYPE (Client Handshake Type) [2 bytes]
- HLEN (Client Handshake Data Len) [2 bytes]
- HDATA (Client Handshake Data) [HLEN bytes]
-```
+| Field | Description | Size |
+| ----- | ----------- | ---- |
+| `NSPEC` | Number of link specifiers | 1 byte
+| `NSPEC` times: |
+| - `LSTYPE` | Link specifier type | 1 byte
+| - `LSLEN` | Link specifier length | 1 byte
+| - `LSPEC` | Link specifier | LSLEN bytes
+| `HTYPE` | Client Handshake Type | 2 bytes
+| `HLEN` | Client Handshake Data Len | 2 bytes
+| `HDATA` | Client Handshake Data | HLEN bytes
Link specifiers describe the next node in the circuit and how to
connect to it. Recognized specifiers are:
-```text
- [00] TLS-over-TCP, IPv4 address
- A four-byte IPv4 address plus two-byte ORPort
- [01] TLS-over-TCP, IPv6 address
- A sixteen-byte IPv6 address plus two-byte ORPort
- [02] Legacy identity
- A 20-byte SHA1 identity fingerprint. At most one may be listed.
- [03] Ed25519 identity
- A 32-byte Ed25519 identity fingerprint. At most one may
- be listed.
-```
+| Value | Description
+| ----- | -----------
+| [00] | TLS-over-TCP, IPv4 address. A four-byte IPv4 address plus two-byte ORPort.
+| [01] | TLS-over-TCP, IPv6 address. A sixteen-byte IPv6 address plus two-byte ORPort.
+| [02] | Legacy identity. A 20-byte SHA1 identity fingerprint. At most one may be listed.
+| [03] | Ed25519 identity. A 32-byte Ed25519 identity fingerprint. At most one may be listed.
Nodes MUST ignore unrecognized specifiers, and MUST accept multiple
instances of specifiers other than 'legacy identity' and
@@ -162,16 +157,17 @@ these link specifiers, if using them, in this order: \[00\], \[02\], \[03\],
The relay payload for an EXTEND relay cell consists of:
-```text
- Address [4 bytes]
- Port [2 bytes]
- Onion skin [TAP_C_HANDSHAKE_LEN bytes]
- Identity fingerprint [HASH_LEN bytes]
-```
+| Field | Size
+| ----- | ----
+| Address | 4 bytes
+| Port | 2 bytes
+| Onion skin | `TAP_C_HANDSHAKE_LEN` bytes
+| Identity fingerprint | `HASH_LEN` bytes
The "legacy identity" and "identity fingerprint" fields are the
SHA1 hash of the PKCS#1 ASN1 encoding of the next onion router's
-identity (signing) key. (See 0.3 above.) The "Ed25519 identity"
+identity (signing) key. (See ["Preliminaries » Ciphers"](./preliminaries.md#ciphers))
+The "Ed25519 identity"
field is the Ed25519 identity key of the target node. Including
this key information allows the extending OR verify that it is
indeed connected to the correct target OR, and prevents certain
@@ -222,55 +218,57 @@ use the format with 'client handshake type tag'.
## The "TAP" handshake {#TAP}
-This handshake uses Diffie-Hellman in Z_p and RSA to compute a set of
+This handshake uses Diffie-Hellman in Z<sub>p</sub> and RSA to compute a set of
shared keys which the client knows are shared only with a particular
server, and the server knows are shared with whomever sent the
original handshake (or with nobody at all). It's not very fast and
not very good. (See Goldberg's "On the Security of the Tor
Authentication Protocol".)
-Define TAP_C_HANDSHAKE_LEN as DH_LEN+KEY_LEN+KP_PAD_LEN.
-Define TAP_S_HANDSHAKE_LEN as DH_LEN+HASH_LEN.
+Define `TAP_C_HANDSHAKE_LEN` as `DH_LEN+KEY_LEN+KP_PAD_LEN`.
+Define `TAP_S_HANDSHAKE_LEN` as `DH_LEN+HASH_LEN`.
The payload for a CREATE cell is an 'onion skin', which consists of
-the first step of the DH handshake data (also known as g^x). This
+the first step of the DH handshake data (also known as `g^x`). This
value is encrypted using the "legacy hybrid encryption" algorithm
-(see 0.4 above) to the server's onion key, giving a client handshake:
-
-```text
- KP-encrypted:
- Padding [KP_PAD_LEN bytes]
- Symmetric key [KEY_LEN bytes]
- First part of g^x [KP_ENC_LEN-KP_PAD_LEN-KEY_LEN bytes]
- Symmetrically encrypted:
- Second part of g^x [DH_LEN-(KP_ENC_LEN-KP_PAD_LEN-KEY_LEN)
- bytes]
-```
+(see ["Preliminaries » A bad hybrid encryption algorithm..."](./preliminaries.md#legacy-hybrid-encryption))
+to the server's onion key, giving a client handshake:
+
+| Field | Size
+| ----- | ----
+| KP-encrypted:
+| - Padding | `KP_PAD_LEN` bytes
+| - Symmetric key | `KEY_LEN` bytes
+| - First part of `g^x` | `KP_ENC_LEN-KP_PAD_LEN-KEY_LEN` bytes
+| Symmetrically encrypted
+| - Second part of `g^x` | `DH_LEN-(KP_ENC_LEN-KP_PAD_LEN-KEY_LEN)` bytes
The payload for a CREATED cell, or the relay payload for an
EXTENDED cell, contains:
-```text
- DH data (g^y) [DH_LEN bytes]
- Derivative key data (KH) [HASH_LEN bytes] <see 5.2 below>
-```
+| Field | Size
+| ----- | ----
+| DH data (`g^y`) | `DH_LEN` bytes
+| Derivative key data (`KH`) | `HASH_LEN` bytes (see ["Setting Circuit Keys"](./setting-circuit-keys.md))
+
Once the handshake between the OP and an OR is completed, both can
-now calculate g^xy with ordinary DH. Before computing g^xy, both parties
-MUST verify that the received g^x or g^y value is not degenerate;
-that is, it must be strictly greater than 1 and strictly less than p-1
-where p is the DH modulus. Implementations MUST NOT complete a handshake
+now calculate `g^xy` with ordinary DH. Before computing `g^xy`, both parties
+MUST verify that the received `g^x` or `g^y` value is not degenerate;
+that is, it must be strictly greater than `1` and strictly less than `p-1`
+where `p` is the DH modulus. Implementations MUST NOT complete a handshake
with degenerate keys. Implementations MUST NOT discard other "weak"
-g^x values.
+`g^x` values.
(Discarding degenerate keys is critical for security; if bad keys
are not discarded, an attacker can substitute the OR's CREATED
-cell's g^y with 0 or 1, thus creating a known g^xy and impersonating
+cell's `g^y` with `0` or `1`, thus creating a known `g^xy` and impersonating
the OR. Discarding other keys may allow attacks to learn bits of
the private key.)
-Once both parties have g^xy, they derive their shared circuit keys
-and 'derivative key data' value via the KDF-TOR function in 5.2.1.
+Once both parties have `g^xy`, they derive their shared circuit keys
+and 'derivative key data' value via the
+[KDF-TOR function](./setting-circuit-keys.md#kdf-tor).
<a id="tor-spec.txt-5.1.4"></a>
@@ -288,68 +286,75 @@ new Diffie-Hellman speed records" by D. J. Bernstein.
In this section, define:
```text
- H(x,t) as HMAC_SHA256 with message x and key t.
- H_LENGTH = 32.
- ID_LENGTH = 20.
- G_LENGTH = 32
- PROTOID = "ntor-curve25519-sha256-1"
- t_mac = PROTOID | ":mac"
- t_key = PROTOID | ":key_extract"
- t_verify = PROTOID | ":verify"
- G = The preferred base point for curve25519 ([9])
- KEYGEN() = The curve25519 key generation algorithm, returning
- a private/public keypair.
- m_expand = PROTOID | ":key_expand"
- KEYID(A) = A
- EXP(a, b) = The ECDH algorithm for establishing a shared secret.
+H(x,t) as HMAC_SHA256 with message x and key t.
+H_LENGTH = 32.
+ID_LENGTH = 20.
+G_LENGTH = 32
+PROTOID = "ntor-curve25519-sha256-1"
+t_mac = PROTOID | ":mac"
+t_key = PROTOID | ":key_extract"
+t_verify = PROTOID | ":verify"
+G = The preferred base point for curve25519 ([9])
+KEYGEN() = The curve25519 key generation algorithm, returning
+ a private/public keypair.
+m_expand = PROTOID | ":key_expand"
+KEYID(A) = A
+EXP(a, b) = The ECDH algorithm for establishing a shared secret.
```
To perform the handshake, the client needs to know an identity key
digest for the server, and an ntor onion key (a curve25519 public
-key) for that server. Call the ntor onion key "B". The client
+key) for that server. Call the ntor onion key `B`. The client
generates a temporary keypair:
+```text
x,X = KEYGEN()
+```
and generates a client-side handshake with contents:
-```text
- NODEID Server identity digest [ID_LENGTH bytes]
- KEYID KEYID(B) [H_LENGTH bytes]
- CLIENT_KP X [G_LENGTH bytes]
-```
+| Field | Value | Size
+| ----- | ----- | ----
+| `NODEID` | Server identity digest | `ID_LENGTH` bytes
+| `KEYID` | KEYID(B) | `H_LENGTH` bytes
+| `CLIENT_KP` | X | `G_LENGTH` bytes
-The server generates a keypair of y,Y = KEYGEN(), and uses its ntor
-private key 'b' to compute:
+The server generates a keypair of `y,Y = KEYGEN()`, and uses its ntor
+private key `b` to compute:
```text
- secret_input = EXP(X,y) | EXP(X,b) | ID | B | X | Y | PROTOID
- KEY_SEED = H(secret_input, t_key)
- verify = H(secret_input, t_verify)
- auth_input = verify | ID | B | Y | X | PROTOID | "Server"
-
- The server's handshake reply is:
+secret_input = EXP(X,y) | EXP(X,b) | ID | B | X | Y | PROTOID
+KEY_SEED = H(secret_input, t_key)
+verify = H(secret_input, t_verify)
+auth_input = verify | ID | B | Y | X | PROTOID | "Server"
+```
- SERVER_KP Y [G_LENGTH bytes]
- AUTH H(auth_input, t_mac) [H_LENGTH bytes]
+The server's handshake reply is:
- The client then checks Y is in G^* [see NOTE below], and computes
+| Field | Value | Size
+| ----- | ----- | ----
+| `SERVER_KP` | `Y` | `G_LENGTH` bytes
+| `AUTH` | `H(auth_input, t_mac)` | `H_LENGTH` bytes
- secret_input = EXP(Y,x) | EXP(B,x) | ID | B | X | Y | PROTOID
- KEY_SEED = H(secret_input, t_key)
- verify = H(secret_input, t_verify)
- auth_input = verify | ID | B | Y | X | PROTOID | "Server"
+The client then checks `Y` is in G<sup>*</sup> [see NOTE below], and computes
- The client verifies that AUTH == H(auth_input, t_mac).
+```text
+secret_input = EXP(Y,x) | EXP(B,x) | ID | B | X | Y | PROTOID
+KEY_SEED = H(secret_input, t_key)
+verify = H(secret_input, t_verify)
+auth_input = verify | ID | B | Y | X | PROTOID | "Server"
```
-Both parties check that none of the EXP() operations produced the
+The client verifies that `AUTH == H(auth_input, t_mac)`.
+
+Both parties check that none of the `EXP()` operations produced the
point at infinity. \[NOTE: This is an adequate replacement for
-checking Y for group membership, if the group is curve25519.\]
+checking `Y` for group membership, if the group is curve25519.\]
-Both parties now have a shared value for KEY_SEED. They expand this
+Both parties now have a shared value for `KEY_SEED`. They expand this
into the keys needed for the Tor relay protocol, using the KDF
-described in 5.2.2 and the tag m_expand.
+described in ["KDF-RFC5869"](./setting-circuit-keys.md#kdf-rfc5869)
+and the tag `m_expand`.
<a id="tor-spec.txt-5.1.4.1"></a>
@@ -368,137 +373,151 @@ To advertise support for this handshake, servers advertise the
In this handshake, we define:
```text
- PROTOID = "ntor3-curve25519-sha3_256-1"
- t_msgkdf = PROTOID | ":kdf_phase1"
- t_msgmac = PROTOID | ":msg_mac"
- t_key_seed = PROTOID | ":key_seed"
- t_verify = PROTOID | ":verify"
- t_final = PROTOID | ":kdf_final"
- t_auth = PROTOID | ":auth_final"
+PROTOID = "ntor3-curve25519-sha3_256-1"
+t_msgkdf = PROTOID | ":kdf_phase1"
+t_msgmac = PROTOID | ":msg_mac"
+t_key_seed = PROTOID | ":key_seed"
+t_verify = PROTOID | ":verify"
+t_final = PROTOID | ":kdf_final"
+t_auth = PROTOID | ":auth_final"
- `ENCAP(s)` -- an encapsulation function. We define this
- as `htonll(len(s)) | s`. (Note that `len(ENCAP(s)) = len(s) + 8`).
+`ENCAP(s)` -- an encapsulation function. We define this
+as `htonll(len(s)) | s`. (Note that `len(ENCAP(s)) = len(s) + 8`).
- `PARTITION(s, n1, n2, n3, ...)` -- a function that partitions a
- bytestring `s` into chunks of length `n1`, `n2`, `n3`, and so
- on. Extra data is put into a final chunk. If `s` is not long
- enough, the function fails.
+`PARTITION(s, n1, n2, n3, ...)` -- a function that partitions a
+bytestring `s` into chunks of length `n1`, `n2`, `n3`, and so
+on. Extra data is put into a final chunk. If `s` is not long
+enough, the function fails.
- H(s, t) = SHA3_256(ENCAP(t) | s)
- MAC(k, msg, t) = SHA3_256(ENCAP(t) | ENCAP(k) | s)
- KDF(s, t) = SHAKE_256(ENCAP(t) | s)
- ENC(k, m) = AES_256_CTR(k, m)
+H(s, t) = SHA3_256(ENCAP(t) | s)
+MAC(k, msg, t) = SHA3_256(ENCAP(t) | ENCAP(k) | s)
+KDF(s, t) = SHAKE_256(ENCAP(t) | s)
+ENC(k, m) = AES_256_CTR(k, m)
- EXP(pk,sk), KEYGEN: defined as in curve25519
+EXP(pk,sk), KEYGEN: defined as in curve25519
- DIGEST_LEN = MAC_LEN = MAC_KEY_LEN = ENC_KEY_LEN = PUB_KEY_LEN = 32
+DIGEST_LEN = MAC_LEN = MAC_KEY_LEN = ENC_KEY_LEN = PUB_KEY_LEN = 32
- ID_LEN = 32 (representing an ed25519 identity key)
+ID_LEN = 32 (representing an ed25519 identity key)
- For any tag "t_foo":
- H_foo(s) = H(s, t_foo)
- MAC_foo(k, msg) = MAC(k, msg, t_foo)
- KDF_foo(s) = KDF(s, t_foo)
+For any tag "t_foo":
+ H_foo(s) = H(s, t_foo)
+ MAC_foo(k, msg) = MAC(k, msg, t_foo)
+ KDF_foo(s) = KDF(s, t_foo)
+```
- Other notation is as in the ntor description in 5.1.4 above.
+Other notation is as in the [ntor description above](#ntor).
- The client begins by knowing:
+The client begins by knowing:
- B, ID -- The curve25519 onion key and Ed25519 ID of the server that it
- wants to use.
- CM -- A message it wants to send as part of its handshake.
- VER -- An optional shared verification string:
+```text
+B, ID -- The curve25519 onion key and Ed25519 ID of the server that it
+ wants to use.
+CM -- A message it wants to send as part of its handshake.
+VER -- An optional shared verification string:
+```
- The client computes:
+The client computes:
- x,X = KEYGEN()
- Bx = EXP(B,x)
- secret_input_phase1 = Bx | ID | X | B | PROTOID | ENCAP(VER)
- phase1_keys = KDF_msgkdf(secret_input_phase1)
- (ENC_K1, MAC_K1) = PARTITION(phase1_keys, ENC_KEY_LEN, MAC_KEY_LEN)
- encrypted_msg = ENC(ENC_K1, CM)
- msg_mac = MAC_msgmac(MAC_K1, ID | B | X | encrypted_msg)
+```text
+x,X = KEYGEN()
+Bx = EXP(B,x)
+secret_input_phase1 = Bx | ID | X | B | PROTOID | ENCAP(VER)
+phase1_keys = KDF_msgkdf(secret_input_phase1)
+(ENC_K1, MAC_K1) = PARTITION(phase1_keys, ENC_KEY_LEN, MAC_KEY_LEN)
+encrypted_msg = ENC(ENC_K1, CM)
+msg_mac = MAC_msgmac(MAC_K1, ID | B | X | encrypted_msg)
+```
- The client then sends, as its CREATE handshake:
+ The client then sends, as its CREATE handshake:
- NODEID ID [ID_LEN bytes]
- KEYID B [PUB_KEY_LEN bytes]
- CLIENT_PK X [PUB_KEY_LEN bytes]
- MSG encrypted_msg [len(CM) bytes]
- MAC msg_mac [MAC_LEN bytes]
+| Field | Value | Size
+| ----- | ----- | ----
+| `NODEID` | `ID` | `ID_LEN` bytes
+| `KEYID` | `B` | `PUB_KEY_LEN` bytes
+| `CLIENT_PK` | `X` | `PUB_KEY_LEN` bytes
+| `MSG` | `encrypted_msg` | `len(CM)` bytes
+| `MAC` | `msg_mac` | `MAC_LEN` bytes
- The client remembers x, X, B, ID, Bx, and msg_mac.
-```
+The client remembers `x`, `X`, `B`, `ID`, `Bx`, and `msg_mac`.
-When the server receives this handshake, it checks whether NODEID is as
-expected, and looks up the (b,B) keypair corresponding to KEYID. If the
-keypair is missing or the NODEID is wrong, the handshake fails.
+When the server receives this handshake, it checks whether `NODEID` is as
+expected, and looks up the `(b,B)` keypair corresponding to `KEYID`. If the
+keypair is missing or the `NODEID` is wrong, the handshake fails.
Now the relay uses `X=CLIENT_PK` to compute:
```text
- Xb = EXP(X,b)
- secret_input_phase1 = Xb | ID | X | B | PROTOID | ENCAP(VER)
- phase1_keys = KDF_msgkdf(secret_input_phase1)
- (ENC_K1, MAC_K1) = PARTITION(phase1_keys, ENC_KEY_LEN, MAC_KEY_LEN)
+Xb = EXP(X,b)
+secret_input_phase1 = Xb | ID | X | B | PROTOID | ENCAP(VER)
+phase1_keys = KDF_msgkdf(secret_input_phase1)
+(ENC_K1, MAC_K1) = PARTITION(phase1_keys, ENC_KEY_LEN, MAC_KEY_LEN)
- expected_mac = MAC_msgmac(MAC_K1, ID | B | X | MSG)
+expected_mac = MAC_msgmac(MAC_K1, ID | B | X | MSG)
```
If `expected_mac` is not `MAC`, the handshake fails. Otherwise
the relay computes `CM` as:
+```text
CM = DEC(MSG, ENC_K1)
+```
The relay then checks whether `CM` is well-formed, and in response
composes `SM`, the reply that it wants to send as part of the
handshake. It then generates a new ephemeral keypair:
+```text
y,Y = KEYGEN()
+```
and computes the rest of the handshake:
```text
- Xy = EXP(X,y)
- secret_input = Xy | Xb | ID | B | X | Y | PROTOID | ENCAP(VER)
- ntor_key_seed = H_key_seed(secret_input)
- verify = H_verify(secret_input)
-
- RAW_KEYSTREAM = KDF_final(ntor_key_seed)
- (ENC_KEY, KEYSTREAM) = PARTITION(RAW_KEYSTREAM, ENC_KEY_LKEN, ...)
+Xy = EXP(X,y)
+secret_input = Xy | Xb | ID | B | X | Y | PROTOID | ENCAP(VER)
+ntor_key_seed = H_key_seed(secret_input)
+verify = H_verify(secret_input)
- encrypted_msg = ENC(ENC_KEY, SM)
+RAW_KEYSTREAM = KDF_final(ntor_key_seed)
+(ENC_KEY, KEYSTREAM) = PARTITION(RAW_KEYSTREAM, ENC_KEY_LKEN, ...)
- auth_input = verify | ID | B | Y | X | MAC | ENCAP(encrypted_msg) |
- PROTOID | "Server"
- AUTH = H_auth(auth_input)
+encrypted_msg = ENC(ENC_KEY, SM)
- The relay then sends as its CREATED handshake:
+auth_input = verify | ID | B | Y | X | MAC | ENCAP(encrypted_msg) |
+ PROTOID | "Server"
+AUTH = H_auth(auth_input)
+```
- Y Y [PUB_KEY_LEN bytes]
- AUTH AUTH [DIGEST_LEN bytes]
- MSG encrypted_msg [len(SM) bytes, up to end of the message]
+The relay then sends as its CREATED handshake:
- Upon receiving this handshake, the client computes:
+| Field | Value | Size
+| ----- | ----- | ----
+| `Y` | `Y` | `PUB_KEY_LEN` bytes
+| `AUTH` | `AUTH` | `DIGEST_LEN` bytes
+| `MSG` | `encrypted_msg` | `len(SM)` bytes, up to end of the message
- Yx = EXP(Y, x)
- secret_input = Yx | Bx | ID | B | X | Y | PROTOID | ENCAP(VER)
- ntor_key_seed = H_key_seed(secret_input)
- verify = H_verify(secret_input)
+Upon receiving this handshake, the client computes:
- auth_input = verify | ID | B | Y | X | MAC | ENCAP(MSG) |
- PROTOID | "Server"
- AUTH_expected = H_auth(auth_input)
+```text
+Yx = EXP(Y, x)
+secret_input = Yx | Bx | ID | B | X | Y | PROTOID | ENCAP(VER)
+ntor_key_seed = H_key_seed(secret_input)
+verify = H_verify(secret_input)
+
+auth_input = verify | ID | B | Y | X | MAC | ENCAP(MSG) |
+ PROTOID | "Server"
+AUTH_expected = H_auth(auth_input)
```
-If AUTH_expected is equal to AUTH, then the handshake has
+If `AUTH_expected` is equal to `AUTH`, then the handshake has
succeeded. The client can then calculate:
```text
- RAW_KEYSTREAM = KDF_final(ntor_key_seed)
- (ENC_KEY, KEYSTREAM) = PARTITION(RAW_KEYSTREAM, ENC_KEY_LKEN, ...)
+RAW_KEYSTREAM = KDF_final(ntor_key_seed)
+(ENC_KEY, KEYSTREAM) = PARTITION(RAW_KEYSTREAM, ENC_KEY_LKEN, ...)
- SM = DEC(ENC_KEY, MSG)
+SM = DEC(ENC_KEY, MSG)
```
SM is the message from the relay, and the client uses KEYSTREAM to
@@ -521,19 +540,21 @@ created.
A CREATE_FAST cell contains:
-Key material (X) \[HASH_LEN bytes\]
+| Field | Size
+| ----- | ----
+| Key material (`X`) | `HASH_LEN` bytes
A CREATED_FAST cell contains:
-```text
- Key material (Y) [HASH_LEN bytes]
- Derivative key data [HASH_LEN bytes] (See 5.2.1 below)
+| Field | Size
+| ----- | ----
+| Key material (`Y`) | `HASH_LEN` bytes
+| Derivative key data | `HASH_LEN` bytes (See [KDF-TOR](./setting-circuit-keys.md#kdf-tor))
- The values of X and Y must be generated randomly.
-```
+The values of `X` and `Y` must be generated randomly.
-Once both parties have X and Y, they derive their shared circuit keys
-and 'derivative key data' value via the KDF-TOR function in 5.2.1.
+Once both parties have `X` and `Y`, they derive their shared circuit keys
+and 'derivative key data' value via the [KDF-TOR function](./setting-circuit-keys.md#kdf-tor).
The CREATE_FAST handshake is currently deprecated whenever it is not
necessary; the migration is controlled by the "usecreatefast"
@@ -550,51 +571,51 @@ relay to send additional data as part of the handshake. When used in a
CREATE/CREATED handshake, this additional data must have the following
format:
-```text
- N_EXTENSIONS [one byte]
- N_EXTENSIONS times:
- EXT_FIELD_TYPE [one byte]
- EXT_FIELD_LEN [one byte]
- EXT_FIELD [EXT_FIELD_LEN bytes]
-
- (`EXT_FIELD_LEN` may be zero, in which case EXT_FIELD is absent.)
-
- All parties MUST reject messages that are not well-formed per the
- rules above.
-
- We do not specify specific TYPE semantics here; we leave those for
- other proposals and specifications.
-
- Parties MUST ignore extensions with `EXT_FIELD_TYPE` bodies they do not
- recognize.
-
- Unless otherwise specified in the documentation for an extension type:
- * Each extension type SHOULD be sent only once in a message.
- * Parties MUST ignore any occurrences all occurrences of an extension
- with a given type after the first such occurrence.
- * Extensions SHOULD be sent in numerically ascending order by type.
-
- (The above extension sorting and multiplicity rules are only defaults;
- they may be overridden in the description of individual extensions.)
-
- Currently supported extensions are:
-
- 1 -- CC_FIELD_REQUEST [Client to server]
-
- Contains an empty payload. Signifies that the client
- wants to use the extended congestion control described
- in proposal 324.
-
- 2 -- CC_FIELD_RESPONSE [Server to client]
-
- Indicates that the relay will use the congestion control
- of proposal 324, as requested by the client. One byte
- in length:
-
- sendme_inc [1 byte]
-
- 3 -- Subprotocol Request [Client to Server]
-
- (RESERVED) Tells the endpoint what protocol version to use on the
- circuit (prop346).
-```
+| Field | Size
+| ----- | ----
+| `N_EXTENSIONS` | one byte
+| `N_EXTENSIONS` times: |
+| - `EXT_FIELD_TYPE` | one byte
+| - `EXT_FIELD_LEN` | one byte
+| - `EXT_FIELD` | `EXT_FIELD_LEN` bytes
+
+(`EXT_FIELD_LEN` may be zero, in which case `EXT_FIELD` is absent.)
+
+All parties MUST reject messages that are not well-formed per the
+rules above.
+
+We do not specify specific TYPE semantics here; we leave those for
+other proposals and specifications.
+
+Parties MUST ignore extensions with `EXT_FIELD_TYPE` bodies they do not
+recognize.
+
+Unless otherwise specified in the documentation for an extension type:
+ * Each extension type SHOULD be sent only once in a message.
+ * Parties MUST ignore any occurrences all occurrences of an extension
+ with a given type after the first such occurrence.
+ * Extensions SHOULD be sent in numerically ascending order by type.
+
+(The above extension sorting and multiplicity rules are only defaults;
+they may be overridden in the description of individual extensions.)
+
+Currently supported extensions are:
+
+ * 1 -- `CC_FIELD_REQUEST` [Client to server]
+
+ Contains an empty payload. Signifies that the client
+ wants to use the extended congestion control described
+ in proposal 324.
+
+ * 2 -- `CC_FIELD_RESPONSE` [Server to client]
+
+ Indicates that the relay will use the congestion control
+ of proposal 324, as requested by the client. One byte
+ in length:
+
+ `sendme_inc [1 byte]`
+
+ * 3 -- Subprotocol Request [Client to Server]
+
+ (RESERVED) Tells the endpoint what protocol version to use on the
+ circuit (prop346).
diff --git a/spec/tor-spec/creating-circuits.md b/spec/tor-spec/creating-circuits.md
index ec595b0..eb8de36 100644
--- a/spec/tor-spec/creating-circuits.md
+++ b/spec/tor-spec/creating-circuits.md
@@ -5,44 +5,42 @@
When creating a circuit through the network, the circuit creator
(OP) performs the following steps:
-```text
- 1. Choose an onion router as an end node (R_N):
- * N MAY be 1 for non-anonymous directory mirror, introduction point,
- or service rendezvous connections.
- * N SHOULD be 3 or more for anonymous connections.
- Some end nodes accept streams (see 6.1), others are introduction
- or rendezvous points (see rend-spec-{v2,v3}.txt).
+1. Choose an onion router as an end node (R_N):
+ * N MAY be 1 for non-anonymous directory mirror, introduction point,
+ or service rendezvous connections.
+ * N SHOULD be 3 or more for anonymous connections.
+ Some end nodes accept streams (see ["Relay Cells"](./relay-cells.md#relay-cells)),
+ others are introduction or rendezvous points (see the [Rendezvous Spec](../rend-spec/index.md)).
- 2. Choose a chain of (N-1) onion routers (R_1...R_N-1) to constitute
- the path, such that no router appears in the path twice.
+2. Choose a chain of (N-1) onion routers (R_1...R_N-1) to constitute
+ the path, such that no router appears in the path twice.
- 3. If not already connected to the first router in the chain,
- open a new connection to that router.
+3. If not already connected to the first router in the chain,
+ open a new connection to that router.
- 4. Choose a circID not already in use on the connection with the
- first router in the chain; send a CREATE/CREATE2 cell along
- the connection, to be received by the first onion router.
+4. Choose a circID not already in use on the connection with the
+ first router in the chain; send a CREATE/CREATE2 cell along
+ the connection, to be received by the first onion router.
- 5. Wait until a CREATED/CREATED2 cell is received; finish the
- handshake and extract the forward key Kf_1 and the backward
- key Kb_1.
+5. Wait until a CREATED/CREATED2 cell is received; finish the
+ handshake and extract the forward key Kf_1 and the backward
+ key Kb_1.
- 6. For each subsequent onion router R (R_2 through R_N), extend
- the circuit to R.
-```
+6. For each subsequent onion router R (R_2 through R_N), extend
+ the circuit to R.
To extend the circuit by a single onion router R_M, the OP performs
these steps:
1. Create an onion skin, encrypted to R_M's public onion key.
-```text
- 2. Send the onion skin in a relay EXTEND/EXTEND2 cell along
- the circuit (see sections 5.1.2 and 5.5).
+2. Send the onion skin in a relay EXTEND/EXTEND2 cell along
+ the circuit (see
+ ["EXTEND and EXTENDED cells"](./create-created-cells.md#EXTEND)
+ and ["Routing relay cells"](./routing-relay-cells.md#routing-relay-cells)).
- 3. When a relay EXTENDED/EXTENDED2 cell is received, verify KH,
- and calculate the shared keys. The circuit is now extended.
-```
+3. When a relay EXTENDED/EXTENDED2 cell is received, verify KH,
+ and calculate the shared keys. The circuit is now extended.
When an onion router receives an EXTEND relay cell, it sends a CREATE
cell to the next onion router, with the enclosed onion skin as its
@@ -52,7 +50,7 @@ When an onion router receives an EXTEND2 relay cell, it sends a CREATE2
cell to the next onion router, with the enclosed HLEN, HTYPE, and HDATA
as its payload. The initiating onion router chooses some circID not yet
used on the connection between the two onion routers. (But see section
-5.1.1 above, concerning choosing circIDs.)
+["Choosing circuit IDs in create cells"](./create-created-cells.md#choosing-circid))
As special cases, if the EXTEND/EXTEND2 cell includes a legacy identity, or
identity fingerprint of all zeroes, or asks to extend back to the relay
@@ -60,7 +58,8 @@ that sent the extend cell, the circuit will fail and be torn down.
Ed25519 identity keys are not required in EXTEND2 cells, so all zero
keys SHOULD be accepted. If the extending relay knows the ed25519 key from
-the consensus, it SHOULD also check that key. (See section 5.1.2.)
+the consensus, it SHOULD also check that key. (See
+[EXTEND and EXTENDED cells](./create-created-cells.md#EXTEND))
If an EXTEND2 cell contains the ed25519 key of the relay that sent the
extend cell, the circuit will fail and be torn down.
@@ -71,7 +70,7 @@ cell. Otherwise, after receiving the CREATE/CREATE2 cell, it completes
the specified handshake, and replies with a CREATED/CREATED2 cell.
Upon receiving a CREATED/CREATED2 cell, an onion router packs it payload
-into an EXTENDED/EXTENDED2 relay cell (see section 5.1.2), and sends
+into an [EXTENDED/EXTENDED2](./create-created-cells.md#EXTEND) relay cell, and sends
that cell up the circuit. Upon receiving the EXTENDED/EXTENDED2 relay
cell, the OP can retrieve the handshake material.
@@ -81,7 +80,7 @@ network latency too greatly.)
<a id="tor-spec.txt-5.3.1"></a>
-## Canonical connections
+## Canonical connections{#canonical-connections}
It is possible for an attacker to launch a man-in-the-middle attack
against a connection by telling OR Alice to extend to OR Bob at some
@@ -94,12 +93,10 @@ To prevent this, when an OR gets an extend request, it SHOULD use an
existing OR connection if the ID matches, and ANY of the following
conditions hold:
-```text
- - The IP matches the requested IP.
- - The OR knows that the IP of the connection it's using is canonical
- because it was listed in the NETINFO cell.
+ - The IP matches the requested IP.
+ - The OR knows that the IP of the connection it's using is canonical
+ because it was listed in the NETINFO cell.
- ORs SHOULD NOT check the IPs that are listed in the server descriptor.
- Trusting server IPs makes it easier to covertly impersonate a relay, after
- stealing its keys.
-```
+ORs SHOULD NOT check the IPs that are listed in the server descriptor.
+Trusting server IPs makes it easier to covertly impersonate a relay, after
+stealing its keys.
diff --git a/spec/tor-spec/negotiating-channels.md b/spec/tor-spec/negotiating-channels.md
index f5cd610..2501d7f 100644
--- a/spec/tor-spec/negotiating-channels.md
+++ b/spec/tor-spec/negotiating-channels.md
@@ -1,68 +1,92 @@
<a id="tor-spec.txt-4"></a>
-# Negotiating and initializing connections{#negotiating-and-initializing-connections}
-
-After Tor instances negotiate handshake with either the "renegotiation" or
-"in-protocol" handshakes, they must exchange a set of cells to set up
-the Tor connection and make it "open" and usable for circuits.
-
-When the renegotiation handshake is used, both parties immediately
-send a [VERSIONS cell](#VERSIONS-cell), and after negotiating a link
-protocol version (which will be 2), each send a [NETINFO cell](#NETINFO-cells)
-to confirm their addresses and timestamps. No other intervening
-cell types are allowed.
-
-When the in-protocol handshake is used, the initiator sends a
-VERSIONS cell to indicate that it will not be renegotiating. The
-responder sends a VERSIONS cell, a [CERTS cell](#CERTS-cells) to give the
-initiator the certificates it needs to learn the responder's
-identity, an [AUTH_CHALLENGE cell](#AUTH-CHALLENGE-cells) that the initiator must include
-as part of its answer if it chooses to authenticate, and a
-[NETINFO cell](#NETINFO-cells). As soon as it gets the CERTS cell, the initiator knows
-whether the responder is correctly authenticated. At this point the
-initiator behaves differently depending on whether it wants to
-authenticate or not. If it does not want to authenticate, it MUST
-send a NETINFO cell. If it does want to authenticate, it MUST send a
-CERTS cell, an [AUTHENTICATE cell](#AUTHENTICATE-cells), and a NETINFO. When this
-handshake is in use, the first cell must be VERSIONS, VPADDING, or
-AUTHORIZE, and no other cell type is allowed to intervene besides
-those specified, except for VPADDING cells.
-
-The AUTHORIZE cell type is reserved for future use by scanning-resistance
-designs.
-
-\[Tor versions before 0.2.3.11-alpha did not recognize the AUTHORIZE cell,
-and did not permit any command other than VERSIONS as the first cell of
-the in-protocol handshake.\]
+# Negotiating and initializing channels {#negotiating}
+
+Here we describe the primary TLS behavior
+used by Tor relays and clients to create a new channel.
+There are older versions of these handshakes,
+which we describe in [another section](./obsolete-channels.md).
+
+In brief:
+ - The initiator starts the handshake
+ by [opening a TLS connection](#tls).
+ - Both parties send a [VERSIONS](#VERSIONS-cell)
+ to negotiate the protocol version to use.
+ - The responder sends a
+ [CERTS cell](#CERTS-cells) to give the
+ initiator the certificates it needs to learn the responder's
+ identity, an [AUTH_CHALLENGE cell](#AUTH-CHALLENGE-cells)
+ that the initiator must include
+ as part of its answer if it chooses to authenticate, and a
+ [NETINFO cell](#NETINFO-cells)
+ to establish clock skew and IP addresses.
+ - The initiator checks whether the CERTS cell is correct,
+ and decides whether to authenticate.
+ - If the initiator does not wants to authenticate,
+ it sends a [NETINFO cell](#NETINFO-cells).
+ - If the initiator wants to authenticate,
+ it sends a [CERTS cell](#CERTS-cells),
+ an [AUTHENTICATE cell](#AUTHENTICATE-cells),
+ a [NETINFO cell](#NETINFO-cells).
+
+When this handshake is in use,
+the first cell must be VERSIONS, VPADDING, or AUTHORIZE,
+and no other cell type is allowed to intervene besides those specified,
+except for VPADDING cells.
+
+(The AUTHORIZE cell type is reserved for future use
+by scanning-resistance designs.
+It is not specified here.)
+
+## The TLS handshake {#tls}
+
+<span id="in-protocol">The
+initiator must send a ciphersuite list containing
+at least one ciphersuite other than
+[those listed in the obsolete v1 handshake](./obsolete-channels.md#v1-ciphersuite-list).
+</span>
+
+> This is trivially achieved
+> by using any modern TLS implementation,
+> and most implementations will not need to worry about it.
+>
+> This requirement distinguishes the current protocol
+> (sometimes called the "in-protocol" or "v3" handshake)
+> from the obsolete v1 protocol.
+
+<a id="tor-spec.txt-2.2"></a>
+
+### TLS security considerations
+
+(Standard TLS security guarantees apply;
+this is not a comprehensive guide.)
+
+Implementations SHOULD NOT allow TLS session resumption -- it can
+exacerbate some attacks (e.g. the "Triple Handshake" attack from
+Feb 2013), and it plays havoc with forward secrecy guarantees.
+
+Implementations SHOULD NOT allow TLS compression -- although we don't
+know a way to apply a CRIME-style attack to current Tor directly,
+it's a waste of resources.
<a id="tor-spec.txt-4.1"></a>
## Negotiating versions with VERSIONS cells {#VERSIONS-cells}
-There are multiple instances of the Tor link connection protocol. Any
-connection negotiated using the "certificates up front" handshake (see
-[Connections](./channels.md#connections)) is "version 1". In any connection where both parties
-have behaved as in the "renegotiation" handshake, the link protocol
-version must be 2. In any connection where both parties have behaved
-as in the "in-protocol" handshake, the link protocol must be 3 or higher.
-
-To determine the version, in any connection where the "renegotiation"
-or "in-protocol" handshake was used (that is, where the responder
-sent only one certificate at first and where the initiator did not
-send any certificates in the first negotiation), both parties MUST
-send a VERSIONS cell. In "renegotiation", they send a VERSIONS cell
-right after the renegotiation is finished, before any other cells are
-sent. In "in-protocol", the initiator sends a VERSIONS cell
-immediately after the initial TLS handshake, and the responder
-replies immediately with a VERSIONS cell. (As an exception to this rule,
-if both sides support the "in-protocol" handshake, either side may send
-VPADDING cells at any time.)
+There are multiple instances of the Tor channel protocol.
+
+Once the TLS handshake is complete,
+both parties send a VERSIONS cell
+to negotiate which one they will use.
The payload in a VERSIONS cell is a series of big-endian two-byte
-integers. Both parties MUST select as the link protocol version the
+integers.
+Both parties MUST select as the link protocol version the
highest number contained both in the VERSIONS cell they sent and in the
-versions cell they received. If they have no such version in common,
-they cannot communicate and MUST close the connection. Either party MUST
+versions cell they received.
+If they have no such version in common,
+they cannot communicate and MUST close the connection.
+Either party MUST
close the connection if the versions cell is not well-formed (for example,
if the payload contains an odd number of bytes).
@@ -70,23 +94,26 @@ Any VERSIONS cells sent after the first VERSIONS cell MUST be ignored.
(To be interpreted correctly, later VERSIONS cells MUST have a CIRCID_LEN
matching the version negotiated with the first VERSIONS cell.)
-Since the version 1 link protocol does not use the "renegotiation"
-handshake, implementations MUST NOT list version 1 in their VERSIONS
-cell. When the "renegotiation" handshake is used, implementations
-MUST list only the version 2. When the "in-protocol" handshake is
-used, implementations MUST NOT list any version before 3, and SHOULD
-list at least version 3.
+> (The
+> [obsolete v1 channel protocol](./obsolete-channels.md#v1-handshake)
+> does note VERSIONS cells.
+> Implementations MUST NOT list version 1 in their VERSIONS cells.
+> The
+> [obsolete v2 channel protocol](./obsolete-channels.md#v2-handshake)
+> can only be used after renegotiation;
+> implementations MUST NOT list version 2 in their VERSIONS cells
+> unless they have renegotiated the TLS session.)
+
+The currently specified [Link](./subprotocol-versioning.md#link) protocols are:
-Link protocols differences are:
+| Version | Description
+| ------- | -----------
+| 1 | (Obsolete) The ["certs up front"](./obsolete-channels.md#v1-handshake) handshake.
+| 2 | (Obsolete) Uses the [renegotiation-based handshake](./obsolete-channels.md#v2-handshake). Introduces variable-length cells.
+| 3 | Uses the [current ("in-protocol") handshake](#in-protocol). Must always be advertised.
+| 4 | Increases circuit ID width to 4 bytes.
+| 5 | Adds support for [link padding](../padding-spec) and negotiation.
-```text
- 1 -- The "certs up front" handshake.
- 2 -- Uses the renegotiation-based handshake. Introduces
- variable-length cells.
- 3 -- Uses the in-protocol handshake.
- 4 -- Increases circuit ID width to 4 bytes.
- 5 -- Adds support for link padding and negotiation (padding-spec.txt).
-```
<a id="tor-spec.txt-4.2"></a>
@@ -95,27 +122,31 @@ Link protocols differences are:
The CERTS cell describes the keys that a Tor instance is claiming
to have. It is a variable-length cell. Its payload format is:
-```text
- N: Number of certs in cell [1 octet]
- N times:
- CertType [1 octet]
- CLEN [2 octets]
- Certificate [CLEN octets]
-
- Any extra octets at the end of a CERTS cell MUST be ignored.
-
- Relevant certType values are:
- 1: Link key certificate certified by RSA1024 identity
- 2: RSA1024 Identity certificate, self-signed.
- 3: RSA1024 AUTHENTICATE cell link certificate, signed with RSA1024 key.
- 4: Ed25519 signing key, signed with identity key.
- 5: TLS link certificate, signed with ed25519 signing key.
- 6: Ed25519 AUTHENTICATE cell key, signed with ed25519 signing key.
- 7: Ed25519 identity, signed with RSA identity.
-```
-
-The certificate format for certificate types 1-3 is DER encoded
-X509. For others, the format is as documented in cert-spec.txt.
+| Field | Description | Size
+| ----- | ----------- | ----
+| N | Number of certs in cell | 1 octet
+| N times: | |
+| - CertType | | 1 octet
+| - CLEN | | 2 octets
+| - Certificate | | CLEN octets
+
+Any extra octets at the end of a CERTS cell MUST be ignored.
+
+Relevant certType values are:
+
+| certType | Description
+| -------- | -----------
+| 1 | Link key certificate certified by RSA1024 identity
+| 2 | RSA1024 Identity certificate, self-signed.
+| 3 | RSA1024 AUTHENTICATE cell link certificate, signed with RSA1024 key.
+| 4 | Ed25519 signing key, signed with identity key.
+| 5 | TLS link certificate, signed with ed25519 signing key.
+| 6 | Ed25519 AUTHENTICATE cell key, signed with ed25519 signing key.
+| 7 | Ed25519 identity, signed with RSA identity.
+
+The certificate format for certificate types 1-3 is DER encoded X509.
+For others, the format is as documented in [a later section](./cert-spec.md)
+
Note that type 7 uses a different format from types 4-6.
A CERTS cell may have no more than one certificate of each CertType.
@@ -123,48 +154,44 @@ A CERTS cell may have no more than one certificate of each CertType.
To authenticate the responder as having a given Ed25519,RSA identity key
combination, the initiator MUST check the following.
-```text
- * The CERTS cell contains exactly one CertType 2 "ID" certificate.
- * The CERTS cell contains exactly one CertType 4 Ed25519
- "Id->Signing" cert.
- * The CERTS cell contains exactly one CertType 5 Ed25519
- "Signing->link" certificate.
- * The CERTS cell contains exactly one CertType 7 "RSA->Ed25519"
- cross-certificate.
- * All X.509 certificates above have validAfter and validUntil dates;
- no X.509 or Ed25519 certificates are expired.
- * All certificates are correctly signed.
- * The certified key in the Signing->Link certificate matches the
- SHA256 digest of the certificate that was used to
- authenticate the TLS connection.
- * The identity key listed in the ID->Signing cert was used to
- sign the ID->Signing Cert.
- * The Signing->Link cert was signed with the Signing key listed
- in the ID->Signing cert.
- * The RSA->Ed25519 cross-certificate certifies the Ed25519
- identity, and is signed with the RSA identity listed in the
- "ID" certificate.
- * The certified key in the ID certificate is a 1024-bit RSA key.
- * The RSA ID certificate is correctly self-signed.
-```
+* The CERTS cell contains exactly one CertType 2 "ID" certificate.
+* The CERTS cell contains exactly one CertType 4 Ed25519
+ "Id->Signing" cert.
+* The CERTS cell contains exactly one CertType 5 Ed25519
+ "Signing->link" certificate.
+* The CERTS cell contains exactly one CertType 7 "RSA->Ed25519"
+ cross-certificate.
+* All X.509 certificates above have validAfter and validUntil dates;
+ no X.509 or Ed25519 certificates are expired.
+* All certificates are correctly signed.
+* The certified key in the Signing->Link certificate matches the
+ SHA256 digest of the certificate that was used to
+ authenticate the TLS connection.
+* The identity key listed in the ID->Signing cert was used to
+ sign the ID->Signing Cert.
+* The Signing->Link cert was signed with the Signing key listed
+ in the ID->Signing cert.
+* The RSA->Ed25519 cross-certificate certifies the Ed25519
+ identity, and is signed with the RSA identity listed in the
+ "ID" certificate.
+* The certified key in the ID certificate is a 1024-bit RSA key.
+* The RSA ID certificate is correctly self-signed.
To authenticate the responder as having a given RSA identity only,
the initiator MUST check the following:
-```text
- * The CERTS cell contains exactly one CertType 1 "Link" certificate.
- * The CERTS cell contains exactly one CertType 2 "ID" certificate.
- * Both certificates have validAfter and validUntil dates that
- are not expired.
- * The certified key in the Link certificate matches the
- link key that was used to negotiate the TLS connection.
- * The certified key in the ID certificate is a 1024-bit RSA key.
- * The certified key in the ID certificate was used to sign both
- certificates.
- * The link certificate is correctly signed with the key in the
- ID certificate
- * The ID certificate is correctly self-signed.
-```
+* The CERTS cell contains exactly one CertType 1 "Link" certificate.
+* The CERTS cell contains exactly one CertType 2 "ID" certificate.
+* Both certificates have validAfter and validUntil dates that
+ are not expired.
+* The certified key in the Link certificate matches the
+ link key that was used to negotiate the TLS connection.
+* The certified key in the ID certificate is a 1024-bit RSA key.
+* The certified key in the ID certificate was used to sign both
+ certificates.
+* The link certificate is correctly signed with the key in the
+ ID certificate
+* The ID certificate is correctly self-signed.
In both cases above, checking these conditions is sufficient to
authenticate that the initiator is talking to the Tor node with the
@@ -173,48 +200,44 @@ expected identity, as certified in the ID certificate(s).
To authenticate the initiator as having a given Ed25519,RSA
identity key combination, the responder MUST check the following:
-```text
- * The CERTS cell contains exactly one CertType 2 "ID" certificate.
- * The CERTS cell contains exactly one CertType 4 Ed25519
- "Id->Signing" certificate.
- * The CERTS cell contains exactly one CertType 6 Ed25519
- "Signing->auth" certificate.
- * The CERTS cell contains exactly one CertType 7 "RSA->Ed25519"
- cross-certificate.
- * All X.509 certificates above have validAfter and validUntil dates;
- no X.509 or Ed25519 certificates are expired.
- * All certificates are correctly signed.
- * The identity key listed in the ID->Signing cert was used to
- sign the ID->Signing Cert.
- * The Signing->AUTH cert was signed with the Signing key listed
- in the ID->Signing cert.
- * The RSA->Ed25519 cross-certificate certifies the Ed25519
- identity, and is signed with the RSA identity listed in the
- "ID" certificate.
- * The certified key in the ID certificate is a 1024-bit RSA key.
- * The RSA ID certificate is correctly self-signed.
-```
+* The CERTS cell contains exactly one CertType 2 "ID" certificate.
+* The CERTS cell contains exactly one CertType 4 Ed25519
+ "Id->Signing" certificate.
+* The CERTS cell contains exactly one CertType 6 Ed25519
+ "Signing->auth" certificate.
+* The CERTS cell contains exactly one CertType 7 "RSA->Ed25519"
+ cross-certificate.
+* All X.509 certificates above have validAfter and validUntil dates;
+ no X.509 or Ed25519 certificates are expired.
+* All certificates are correctly signed.
+* The identity key listed in the ID->Signing cert was used to
+ sign the ID->Signing Cert.
+* The Signing->AUTH cert was signed with the Signing key listed
+ in the ID->Signing cert.
+* The RSA->Ed25519 cross-certificate certifies the Ed25519
+ identity, and is signed with the RSA identity listed in the
+ "ID" certificate.
+* The certified key in the ID certificate is a 1024-bit RSA key.
+* The RSA ID certificate is correctly self-signed.
To authenticate the initiator as having an RSA identity key only,
the responder MUST check the following:
-```text
- * The CERTS cell contains exactly one CertType 3 "AUTH" certificate.
- * The CERTS cell contains exactly one CertType 2 "ID" certificate.
- * Both certificates have validAfter and validUntil dates that
- are not expired.
- * The certified key in the AUTH certificate is a 1024-bit RSA key.
- * The certified key in the ID certificate is a 1024-bit RSA key.
- * The certified key in the ID certificate was used to sign both
- certificates.
- * The auth certificate is correctly signed with the key in the
- ID certificate.
- * The ID certificate is correctly self-signed.
-```
+* The CERTS cell contains exactly one CertType 3 "AUTH" certificate.
+* The CERTS cell contains exactly one CertType 2 "ID" certificate.
+* Both certificates have validAfter and validUntil dates that
+ are not expired.
+* The certified key in the AUTH certificate is a 1024-bit RSA key.
+* The certified key in the ID certificate is a 1024-bit RSA key.
+* The certified key in the ID certificate was used to sign both
+ certificates.
+* The auth certificate is correctly signed with the key in the
+ ID certificate.
+* The ID certificate is correctly self-signed.
Checking these conditions is NOT sufficient to authenticate that the
-initiator has the ID it claims; to do so, the cells in 4.3 and 4.4
-below must be exchanged.
+initiator has the ID it claims; to do so, [AUTH_CHALLENGE](#AUTH-CHALLENGE-cells)
+and [AUTHENTICATE](#AUTHENTICATE-cells) cells (described next) must be exchanged.
<a id="tor-spec.txt-4.3"></a>
@@ -223,11 +246,11 @@ below must be exchanged.
An AUTH_CHALLENGE cell is a variable-length cell with the following
fields:
-```text
- Challenge [32 octets]
- N_Methods [2 octets]
- Methods [2 * N_Methods octets]
-```
+| Field | Size
+| ----- | ----
+| Challenge | 32 octets
+| N_Methods | 2 octets
+| Methods | 2 * N_Methods octets
It is sent from the responder to the initiator. Initiators MUST
ignore unexpected bytes at the end of the cell. Responders MUST
@@ -237,7 +260,8 @@ The Challenge field is a randomly generated string that the
initiator must sign (a hash of) as part of authenticating. The
methods are the authentication methods that the responder will
accept. Only two authentication methods are defined right now:
-see 4.4.1 and 4.4.2 below.
+see [RSA-SHA256-TLSSecret](#RSA-SHA256-TLSSecret) and
+[Ed25519-SHA256-RFC570](#Ed25519-SHA256-RFC5705) below.
<a id="tor-spec.txt-4.4"></a>
@@ -252,15 +276,17 @@ CertType 6) cert for an RSA/Ed25519 AUTHENTICATE key.
This difference is because we allow any link key type on a TLS
link, but the protocol described here will only work for specific key
-types as described in 4.4.1 and 4.4.2 below.
+types as described in
+[RSA-SHA256-TLSSecret](#RSA-SHA256-TLSSecret) and
+[Ed25519-SHA256-RFC570](#Ed25519-SHA256-RFC5705) below.
An AUTHENTICATE cell contains the following:
-```text
- AuthType [2 octets]
- AuthLen [2 octets]
- Authentication [AuthLen octets]
-```
+| Field | Size
+| ----- | ----
+| AuthType | 2 octets
+| AuthLen | 2 octets
+| Authentication | AuthLen octets
Responders MUST ignore extra bytes at the end of an AUTHENTICATE
cell. Recognized AuthTypes are 1 and 3, described in the next
@@ -277,37 +303,34 @@ cell, and authenticated the responder.
If AuthType is 1 (meaning "RSA-SHA256-TLSSecret"), then the
Authentication field of the AUTHENTICATE cell contains the following:
-```text
- TYPE: The characters "AUTH0001" [8 octets]
- CID: A SHA256 hash of the initiator's RSA1024 identity key [32 octets]
- SID: A SHA256 hash of the responder's RSA1024 identity key [32 octets]
- SLOG: A SHA256 hash of all bytes sent from the responder to the
- initiator as part of the negotiation up to and including the
- AUTH_CHALLENGE cell; that is, the VERSIONS cell, the CERTS cell,
- the AUTH_CHALLENGE cell, and any padding cells. [32 octets]
- CLOG: A SHA256 hash of all bytes sent from the initiator to the
- responder as part of the negotiation so far; that is, the
- VERSIONS cell and the CERTS cell and any padding cells. [32
- octets]
- SCERT: A SHA256 hash of the responder's TLS link certificate. [32
- octets]
- TLSSECRETS: A SHA256 HMAC, using the TLS master secret as the
- secret key, of the following:
- - client_random, as sent in the TLS Client Hello
- - server_random, as sent in the TLS Server Hello
- - the NUL terminated ASCII string:
- "Tor V3 handshake TLS cross-certification"
- [32 octets]
- RAND: A 24 byte value, randomly chosen by the initiator. (In an
- imitation of SSL3's gmt_unix_time field, older versions of Tor
- sent an 8-byte timestamp as the first 8 bytes of this field;
- new implementations should not do that.) [24 octets]
- SIG: A signature of a SHA256 hash of all the previous fields
- using the initiator's "Authenticate" key as presented. (As
- always in Tor, we use OAEP-MGF1 padding; see tor-spec.txt
- section 0.3.)
- [variable length]
-```
+* TYPE: The characters "AUTH0001" [8 octets]
+* CID: A SHA256 hash of the initiator's RSA1024 identity key [32 octets]
+* SID: A SHA256 hash of the responder's RSA1024 identity key [32 octets]
+* SLOG: A SHA256 hash of all bytes sent from the responder to the
+ initiator as part of the negotiation up to and including the
+ AUTH_CHALLENGE cell; that is, the VERSIONS cell, the CERTS cell,
+ the AUTH_CHALLENGE cell, and any padding cells. [32 octets]
+* CLOG: A SHA256 hash of all bytes sent from the initiator to the
+ responder as part of the negotiation so far; that is, the
+ VERSIONS cell and the CERTS cell and any padding cells. [32
+ octets]
+* SCERT: A SHA256 hash of the responder's TLS link certificate. [32
+ octets]
+* TLSSECRETS: A SHA256 HMAC, using the TLS master secret as the
+ secret key, of the following:
+ - client_random, as sent in the TLS Client Hello
+ - server_random, as sent in the TLS Server Hello
+ - the NUL terminated ASCII string:
+ "Tor V3 handshake TLS cross-certification"
+ [32 octets]
+* RAND: A 24 byte value, randomly chosen by the initiator. (In an
+ imitation of SSL3's gmt_unix_time field, older versions of Tor
+ sent an 8-byte timestamp as the first 8 bytes of this field;
+ new implementations should not do that.) [24 octets]
+* SIG: A signature of a SHA256 hash of all the previous fields
+ using the initiator's "Authenticate" key as presented. (As
+ always in Tor, we use OAEP-MGF1 padding; see [Ciphers](./preliminaries.md#ciphers))
+ [variable length]
To check the AUTHENTICATE cell, a responder checks that all fields
from TYPE through TLSSECRETS contain their unique
@@ -329,33 +352,31 @@ Authentication field of the AuthType cell is as below:
Modified values and new fields below are marked with asterisks.
-```text
- TYPE: The characters "AUTH0003" [8 octets]
- CID: A SHA256 hash of the initiator's RSA1024 identity key [32 octets]
- SID: A SHA256 hash of the responder's RSA1024 identity key [32 octets]
- CID_ED: The initiator's Ed25519 identity key [32 octets]
- SID_ED: The responder's Ed25519 identity key, or all-zero. [32 octets]
- SLOG: A SHA256 hash of all bytes sent from the responder to the
- initiator as part of the negotiation up to and including the
- AUTH_CHALLENGE cell; that is, the VERSIONS cell, the CERTS cell,
- the AUTH_CHALLENGE cell, and any padding cells. [32 octets]
- CLOG: A SHA256 hash of all bytes sent from the initiator to the
- responder as part of the negotiation so far; that is, the
- VERSIONS cell and the CERTS cell and any padding cells. [32
- octets]
- SCERT: A SHA256 hash of the responder's TLS link certificate. [32
- octets]
- TLSSECRETS: The output of an RFC5705 Exporter function on the
- TLS session, using as its inputs:
- - The label string "EXPORTER FOR TOR TLS CLIENT BINDING AUTH0003"
- - The context value equal to the initiator's Ed25519 identity key.
- - The length 32.
- [32 octets]
- RAND: A 24 byte value, randomly chosen by the initiator. [24 octets]
- SIG: A signature of all previous fields using the initiator's
- Ed25519 authentication key (as in the cert with CertType 6).
- [variable length]
-```
+* TYPE: The characters "AUTH0003" [8 octets]
+* CID: A SHA256 hash of the initiator's RSA1024 identity key [32 octets]
+* SID: A SHA256 hash of the responder's RSA1024 identity key [32 octets]
+* CID_ED: The initiator's Ed25519 identity key [32 octets]
+* SID_ED: The responder's Ed25519 identity key, or all-zero. [32 octets]
+* SLOG: A SHA256 hash of all bytes sent from the responder to the
+ initiator as part of the negotiation up to and including the
+ AUTH_CHALLENGE cell; that is, the VERSIONS cell, the CERTS cell,
+ the AUTH_CHALLENGE cell, and any padding cells. [32 octets]
+* CLOG: A SHA256 hash of all bytes sent from the initiator to the
+ responder as part of the negotiation so far; that is, the
+ VERSIONS cell and the CERTS cell and any padding cells. [32
+ octets]
+* SCERT: A SHA256 hash of the responder's TLS link certificate. [32
+ octets]
+* TLSSECRETS: The output of an RFC5705 Exporter function on the
+ TLS session, using as its inputs:
+ - The label string "EXPORTER FOR TOR TLS CLIENT BINDING AUTH0003"
+ - The context value equal to the initiator's Ed25519 identity key.
+ - The length 32.
+ [32 octets]
+* RAND: A 24 byte value, randomly chosen by the initiator. [24 octets]
+* SIG: A signature of all previous fields using the initiator's
+ Ed25519 authentication key (as in the cert with CertType 6).
+ [variable length]
To check the AUTHENTICATE cell, a responder checks that all fields
from TYPE through TLSSECRETS contain their unique
@@ -370,23 +391,25 @@ the RAND field.
If version 2 or higher is negotiated, each party sends the other a
NETINFO cell. The cell's payload is:
-```text
- TIME (Timestamp) [4 bytes]
- OTHERADDR (Other OR's address) [variable]
- ATYPE (Address type) [1 byte]
- ALEN (Address length) [1 byte]
- AVAL (Address value in NBO) [ALEN bytes]
- NMYADDR (Number of this OR's addresses) [1 byte]
- NMYADDR times:
- ATYPE (Address type) [1 byte]
- ALEN (Address length) [1 byte]
- AVAL (Address value in NBO)) [ALEN bytes]
-
- Recognized address types (ATYPE) are:
-
- [04] IPv4.
- [06] IPv6.
-```
+| Field | Description | Size
+| ----- | ----------- | ----
+| TIME | Timestamp | 4 bytes
+| OTHERADDR: | Other OR's address |
+| - ATYPE | Address type | 1 byte
+| - ALEN | Address length | 1 byte
+| - AVAL | Address value in NBO | ALEN bytes
+| NMYADDR | Number of this OR's addresses | 1 byte
+| NMYADDR times: | |
+| - ATYPE | Address type | 1 byte
+| - ALEN | Address length | 1 byte
+| - AVAL | Address value in NBO | ALEN bytes
+
+Recognized address types (ATYPE) are:
+
+| ATYPE | Description
+| ----- | -----------
+| 0x04 | IPv4
+| 0x06 | IPv6
ALEN MUST be 4 when ATYPE is 0x04 (IPv4) and 16 when ATYPE is 0x06
(IPv6). If the ALEN value is wrong for the given ATYPE value, then
@@ -407,4 +430,4 @@ since the other party can lie about the time or IP addresses it sees.
Initiators SHOULD use "this OR's address" to make sure
that they have connected to another OR at its canonical address.
-(See 5.3.1 below.)
+(See [Canonical connections](./creating-circuits.md#canonical-connections))
diff --git a/spec/tor-spec/obsolete-channels.md b/spec/tor-spec/obsolete-channels.md
new file mode 100644
index 0000000..5f3c053
--- /dev/null
+++ b/spec/tor-spec/obsolete-channels.md
@@ -0,0 +1,168 @@
+# Obsolete channel handshakes
+
+These handshake variants are no longer in use.
+Channel initiators MUST NOT send them.
+Relays MAY detect and reject them.
+
+> If you are experienced with TLS,
+> you will find some aspects of this handshake
+> strange or obfuscated.
+> Several historical factors led to its current state.
+>
+> First, before the development of
+> [pluggable transports](../pt-spec/),
+> Tor tried to avoid censorship by mimicking the behavior
+> of a web client negotiating HTTPS with a web server.
+> If we wanted a secure option that was not in common use,
+> we had to hide our use of that option.
+>
+> Second, prior to the introduction of
+> [TLS 1.3](https://datatracker.ietf.org/doc/html/rfc8446),
+> many more aspects of the handshake
+> (such as the number and nature of certificates sent by each party)
+> were sent in the clear,
+> and were easy to distinguish.
+>
+> Third, prior to the introduction of TLS 1.3,
+> there was no good encrypted signalling mechanism
+> that a client could use to declare
+> how it wanted the rest of the TLS handshake to proceed.
+> Thus, we wound up using the client's list
+> of supported ciphersuites
+> to send a signal about which variation of the handshake is in use.
+
+
+### Version 1, or "certificates up front" {#v1-handshake}
+
+With this obsolete handshake,
+the responding relay proves ownership of an RSA identity (`KP_relayid_rsa`),
+and the initiator also proves ownership of an RSA identity.
+
+(If the initiator does not have an RSA identity to prove,
+it invents one and throws it away afterwards.)
+
+To select this handshake,
+the initiator starts a TLS handshake
+containing no ciphersuites other than these:
+
+<a id="v1-ciphersuite-list"></a>
+```text
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+```
+
+> Note that because of this list,
+> it is impossible to use this obsolete handshake
+> with TLS 1.3.
+
+
+As part of the TLS handshake,
+the initiator sends a two-certificate chain,
+consisting of an X.509 certificate
+for its short-term connection public key (`KP_legacy_conn_tls`)
+signed by `KP_relayid_rsa`, and
+a second self-signed X.509 certificate containing `KP_relayid_rsa`.
+The responder sends a similar
+certificate chain.
+
+Once the TLS handshake is done,
+both parties validate each other's certificate chains.
+If they are valid,
+then the connection is Open,
+and both parties may start exchanging [cells](./cell-packet-format.md).
+
+## Version 2, or "renegotiation" {#v2-handshake}
+
+In "renegotiation" (a.k.a. "the v2 handshake"),
+the connection initiator selects at least one ciphersuite
+not in the [list above](#v1-ciphersuite-list).
+The initiator sends no certificates, and
+the responder sends a single connection certificate in return.
+
+(If the responder sends a certificate chain,
+the initiator assumes that it only knows about the v1 handshake.)
+
+Once this initial TLS handshake is complete,
+the initiator renegotiates the session.
+During the renegotiation,
+each party sends a two-certificate chain
+as in the ["certificates up front"](#v1-handshake) handshake above.
+
+When this handshake is used,
+both parties immediately
+send a VERSIONS cell, and after negotiating a link
+protocol version (which will be 2), each sends a NETINFO cell
+to confirm their addresses and timestamps.
+At that point, the channel is Open.
+No other intervening cell types are allowed.
+
+## Indicating support for the in-protocol handshake
+
+When the in-protocol handshake was new,
+we placed a set of constraints on the certificate that the responder would send
+to indicate that it supported the v3 handshake.
+
+Specifically, if at least one of these properties
+was true of the responders's certificate,
+the initiator could be sure that the responder supported
+the in-protocol handshake:
+
+- The certificate is self-signed
+- Some component other than "commonName" is set in the subject or
+ issuer DN of the certificate.
+- The commonName of the subject or issuer of the certificate ends
+ with a suffix other than ".net".
+- The certificate's public key modulus is longer than 1024 bits.
+
+Otherwise, the initiator would assume
+that only the v2 protocol was in use.
+
+## Fixed ciphersuite list {#fixed-cipehrsuite-list}
+
+For a long time, clients would advertise
+a certain "fixed ciphersuite list"
+regardless of whether they actually supported those ciphers.
+
+That list is:
+
+```text
+ TLS1_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+ TLS1_ECDHE_RSA_WITH_AES_256_CBC_SHA
+ TLS1_DHE_RSA_WITH_AES_256_SHA
+ TLS1_DHE_DSS_WITH_AES_256_SHA
+ TLS1_ECDH_RSA_WITH_AES_256_CBC_SHA
+ TLS1_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+ TLS1_RSA_WITH_AES_256_SHA
+ TLS1_ECDHE_ECDSA_WITH_RC4_128_SHA
+ TLS1_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+ TLS1_ECDHE_RSA_WITH_RC4_128_SHA
+ TLS1_ECDHE_RSA_WITH_AES_128_CBC_SHA
+ TLS1_DHE_RSA_WITH_AES_128_SHA
+ TLS1_DHE_DSS_WITH_AES_128_SHA
+ TLS1_ECDH_RSA_WITH_RC4_128_SHA
+ TLS1_ECDH_RSA_WITH_AES_128_CBC_SHA
+ TLS1_ECDH_ECDSA_WITH_RC4_128_SHA
+ TLS1_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+ SSL3_RSA_RC4_128_MD5
+ SSL3_RSA_RC4_128_SHA
+ TLS1_RSA_WITH_AES_128_SHA
+ TLS1_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA
+ TLS1_ECDHE_RSA_WITH_DES_192_CBC3_SHA
+ SSL3_EDH_RSA_DES_192_CBC3_SHA
+ SSL3_EDH_DSS_DES_192_CBC3_SHA
+ TLS1_ECDH_RSA_WITH_DES_192_CBC3_SHA
+ TLS1_ECDH_ECDSA_WITH_DES_192_CBC3_SHA
+ SSL3_RSA_FIPS_WITH_3DES_EDE_CBC_SHA
+ SSL3_RSA_DES_192_CBC3_SHA
+ [*] The "extended renegotiation is supported" ciphersuite, 0x00ff, is
+ not counted when checking the list of ciphersuites.
+```
+
+When encountering this list,
+a responder would not select any ciphersuites
+besides the mandatory-to-implement
+TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+and SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA.
+
+Clients no longer report ciphers that they do not support.
diff --git a/spec/tor-spec/opening-streams.md b/spec/tor-spec/opening-streams.md
index c3a0aa6..d59e26b 100644
--- a/spec/tor-spec/opening-streams.md
+++ b/spec/tor-spec/opening-streams.md
@@ -26,7 +26,8 @@ fingerprinting. Implementations MUST accept strings in any case.
The FLAGS value has one or more of the following bits set, where
"bit 1" is the LSB of the 32-bit value, and "bit 32" is the MSB.
-(Remember that all values in Tor are big-endian (see 0.1.1 above), so
+(Remember that all values in Tor are big-endian (see
+["Preliminaries » Encoding integers"](./preliminaries.md#encoding)), so
the MSB of a 4-byte value is the MSB of the first byte, and the LSB
of a 4-byte value is the LSB of its last byte.)
@@ -49,7 +50,8 @@ FLAGS, FLAGS is omitted from the message payload.
Upon receiving this cell, the exit node resolves the address as
necessary, and opens a new TCP connection to the target port. If the
address cannot be resolved, or a connection can't be established, the
-exit node replies with a RELAY_END cell. (See 6.3 below.)
+exit node replies with a RELAY_END cell. (See
+["Closing streams"](./closing-streams.md#closing-streams).)
Otherwise, the exit node replies with a RELAY_CONNECTED cell, whose
payload is in one of the following formats:
diff --git a/spec/tor-spec/preliminaries.md b/spec/tor-spec/preliminaries.md
index f5dce7d..36468d8 100644
--- a/spec/tor-spec/preliminaries.md
+++ b/spec/tor-spec/preliminaries.md
@@ -11,7 +11,7 @@
<a id="tor-spec.txt-0.1"></a>
-## Notation and encoding
+## Notation and encoding{#notation-and-encoding}
```text
KP -- a public key for an asymmetric cipher.
@@ -34,7 +34,7 @@ Some specs mention "base32". This means RFC4648, without "=" padding.
<a id="tor-spec.txt-0.1.1"></a>
-### Encoding integers
+### Encoding integers{#encoding}
Unless we explicitly say otherwise below, all numeric values in the
Tor protocol are encoded in network (big-endian) order. So a "32-bit
@@ -72,7 +72,7 @@ KEY_LEN -- the length of the stream cipher's key, in bytes.
<a id="tor-spec.txt-0.3"></a>
-## Ciphers
+## Ciphers{#ciphers}
These are the ciphers we use _unless otherwise specified_. Several of
them are deprecated for new use.
diff --git a/spec/tor-spec/relay-cells.md b/spec/tor-spec/relay-cells.md
index add1f42..e704d6a 100644
--- a/spec/tor-spec/relay-cells.md
+++ b/spec/tor-spec/relay-cells.md
@@ -15,45 +15,47 @@ End nodes that accept streams may be:
The payload of each unencrypted RELAY cell consists of:
-```text
- Relay command [1 byte]
- 'Recognized' [2 bytes]
- StreamID [2 bytes]
- Digest [4 bytes]
- Length [2 bytes]
- Data [Length bytes]
- Padding [PAYLOAD_LEN - 11 - Length bytes]
-
- The relay commands are:
-
- 1 -- RELAY_BEGIN [forward]
- 2 -- RELAY_DATA [forward or backward]
- 3 -- RELAY_END [forward or backward]
- 4 -- RELAY_CONNECTED [backward]
- 5 -- RELAY_SENDME [forward or backward] [sometimes control]
- 6 -- RELAY_EXTEND [forward] [control]
- 7 -- RELAY_EXTENDED [backward] [control]
- 8 -- RELAY_TRUNCATE [forward] [control]
- 9 -- RELAY_TRUNCATED [backward] [control]
- 10 -- RELAY_DROP [forward or backward] [control]
- 11 -- RELAY_RESOLVE [forward]
- 12 -- RELAY_RESOLVED [backward]
- 13 -- RELAY_BEGIN_DIR [forward]
- 14 -- RELAY_EXTEND2 [forward] [control]
- 15 -- RELAY_EXTENDED2 [backward] [control]
-
- 16..18 -- Reserved for UDP; Not yet in use, see prop339.
-
- 19..22 -- Reserved for Conflux, see prop329.
-
- 32..40 -- Used for hidden services; see rend-spec-{v2,v3}.txt.
-
- 41..42 -- Used for circuit padding; see Section 3 of padding-spec.txt.
-
- Used for flow control; see Section 4 of prop324.
- 43 -- XON [forward or backward]
- 44 -- XOFF [forward or backward]
-```
+| Field | Size
+| ----- | ----
+| Relay command | 1 byte
+| 'Recognized' | 2 bytes
+| StreamID | 2 bytes
+| Digest | 4 bytes
+| Length | 2 bytes
+| Data | Length bytes
+| Padding | PAYLOAD_LEN - 11 - Length bytes
+
+The relay commands are:
+
+| Command | Identifier | Direction | Control?
+| ------- | ---------- | --------- | --------
+| 1 | RELAY_BEGIN | forward |
+| 2 | RELAY_DATA | forward or backward |
+| 3 | RELAY_END | forward or backward |
+| 4 | RELAY_CONNECTED | backward |
+| 5 | RELAY_SENDME | forward or backward | sometimes control
+| 6 | RELAY_EXTEND | forward | control
+| 7 | RELAY_EXTENDED | backward | control
+| 8 | RELAY_TRUNCATE | forward | control
+| 9 | RELAY_TRUNCATED | backward | control
+| 10 | RELAY_DROP | forward or backward | control
+| 11 | RELAY_RESOLVE | forward |
+| 12 | RELAY_RESOLVED | backward |
+| 13 | RELAY_BEGIN_DIR | forward |
+| 14 | RELAY_EXTEND2 | forward | control
+| 15 | RELAY_EXTENDED2 | backward | control
+| 16..18 | Reserved for UDP; Not yet in use, see [prop339][prop339].
+| 19..22 | Reserved for Conflux, see [prop329][prop329].
+| 32..40 | Used for hidden services; see the [rendezvous spec][rend-spec].
+| 41..42 | Used for circuit padding; see ["Circuit-level padding"][circ-padding] in the padding spec.
+| 43 | XON (See Sec 4 of [prop324][prop324]) | forward or backward |
+| 44 | XOFF (See Sec 4 of [prop324][prop324]) | forward or backward |
+
+[prop324]: ../proposals/324-rtt-congestion-control.txt
+[prop329]: ../proposals/329-traffic-splitting.md
+[prop339]: ../proposals/339-udp-over-tor.md
+[rend-spec]: ../rend-spec/index.md
+[circ-padding]: ../padding-spec/circuit-level-padding.md#circuit-level-padding
Commands labelled as "forward" must only be sent by the originator
of the circuit. Commands labelled as "backward" must only be sent by
@@ -127,34 +129,36 @@ single field, namely 'Recognized' is not sufficient, as outlined above.
When ENCRYPTING a RELAY cell, an implementation does the following:
```text
- # Encode the cell in binary (recognized and digest set to zero)
- tmp = cmd + [0, 0] + stream_id + [0, 0, 0, 0] + length + data + padding
+# Encode the cell in binary (recognized and digest set to zero)
+tmp = cmd + [0, 0] + stream_id + [0, 0, 0, 0] + length + data + padding
- # Update the digest with the encoded data
- digest_state = hash_update(digest_state, tmp)
- digest = hash_calculate(digest_state)
+# Update the digest with the encoded data
+digest_state = hash_update(digest_state, tmp)
+digest = hash_calculate(digest_state)
- # The encoded data is the same as above with the digest field not being
- # zero anymore
- encoded = cmd + [0, 0] + stream_id + digest[0..4] + length + data +
- padding
+# The encoded data is the same as above with the digest field not being
+# zero anymore
+encoded = cmd + [0, 0] + stream_id + digest[0..4] + length + data +
+ padding
- # Now we can encrypt the cell by adding the onion layers ...
+# Now we can encrypt the cell by adding the onion layers ...
+```
- When DECRYPTING a RELAY cell, an implementation does the following:
+ When DECRYPTING a RELAY cell, an implementation does the following:
- decrypted = decrypt(cell)
+```text
+decrypted = decrypt(cell)
- # Replace the digest field in decrypted by zeros
- tmp = decrypted[0..5] + [0, 0, 0, 0] + decrypted[9..]
+# Replace the digest field in decrypted by zeros
+tmp = decrypted[0..5] + [0, 0, 0, 0] + decrypted[9..]
- # Update the digest field with the decrypted data and its digest field
- # set to zero
- digest_state = hash_update(digest_state, tmp)
- digest = hash_calculate(digest_state)
+# Update the digest field with the decrypted data and its digest field
+# set to zero
+digest_state = hash_update(digest_state, tmp)
+digest = hash_calculate(digest_state)
- if digest[0..4] == decrypted[5..9]
- # The cell has been fully decrypted ...
+if digest[0..4] == decrypted[5..9]
+ # The cell has been fully decrypted ...
```
The caveat itself is that only the binary data with the digest bytes set to
diff --git a/spec/tor-spec/relay-keys.md b/spec/tor-spec/relay-keys.md
new file mode 100644
index 0000000..42b4c3c
--- /dev/null
+++ b/spec/tor-spec/relay-keys.md
@@ -0,0 +1,161 @@
+<a id="tor-spec.txt-1.1"></a>
+
+# Relay keys and identities
+
+Every Tor relay has multiple public/private keypairs,
+with different lifetimes and purposes.
+We explain them here.
+
+Each key here has an English name
+(like "Ed25519 identity key")
+and an unambiguous identifier
+(like `KP_relayid_ed`).
+
+In an identifier,
+a `KP_` prefix denotes a public key,
+and a `KS_` prefix denotes the corresponding secret key.
+
+> For historical reasons or reasons of space,
+> you will sometimes encounter
+> multiple English names for the same key,
+> or shortened versions of that name.
+> The identifier for a key, however,
+> should always be unique and unambiguous.
+
+For security reasons, **all keys MUST be distinct**:
+the same key or keypair should never be used
+for separate roles within the Tor protocol suite,
+unless specifically stated.
+For example,
+a relay's identity key `KP_relayid_ed`
+MUST NOT also be used
+as its medium-term signing key `KP_relaysign_ed`.
+
+## Identity keys
+
+An **identity key** is a long-lived key
+that uniquely identifies a relay.
+Two relays with the same set of identity keys
+are considered to be the same;
+any relay that changes its identity key
+is considered to have become a different relay.
+
+An identity keypair's lifetime
+is the same as the lifetime of the relay.
+
+Two identity keys are currently defined:
+
+- `KP_relayid_ed`, `KS_relayid_ed`:
+ An "ed25519 identity key",
+ also sometimes called a "master identity key".
+
+ This is an Ed25519 key.
+ This key never expires.
+ It is used for only one purpose:
+ signing the `KP_relaysign_ed` key,
+ which is used to sign
+ other important keys and objects.
+
+- `KP_relayid_rsa`, `KS_relayid_rsa`.
+ A _legacy_ "RSA identity key".
+
+ This is an RSA key.
+ It never expires.
+ It is always 1024 bits long,
+ and (as discussed [above](./preliminaries.md#ciphers))
+ its exponent must be 65537.
+ It is used to sign directory documents and certificates.
+
+Note that because the legacy RSA identity key is so short,
+it should not be assumed secure against an attacker.
+It exists for legacy purposes only.
+When authenticating a relay,
+a failure to prove an expected RSA identity
+is sufficient evidence of a _failure_ to authenticate,
+but a successful proof of an RSA identity is not sufficient
+to establish a relay's identity.
+Parties SHOULD NOT use the RSA identity on its own.
+
+We write `KP_relayid` to refer to a key which is either
+`KP_relayid_rsa` or `KP_relayid_ed`.
+
+## Online signing keys
+
+Since Tor's design tries to support
+keeping the high-value Ed25519 relay identity key offline,
+we need a corresponding key that can be used for online signing:
+
+- `KP_relaysign_ed`, `KS_relaysign_ed`:
+ A medium-term Ed25519 "signing" key.
+ This key is signed by the identity key `KP_relayid_ed`,
+ and must be kept online.
+ A new one should be generated periodically.
+ It signs nearly everything else,
+ including directory objects,
+ and certificates for other keys.
+
+
+## Circuit extension keys
+
+Each relay has one or more **circuit extension keys**
+(also called "onion keys").
+When [creating](./create-created-cells.md)
+or [extending](./create-created-cells.md#EXTEND)
+a circuit,
+a client uses this key to perform
+a [one-way authenticated key exchange][cacr2011-goldberg]
+with the target relay.
+If the recipient does not have the correct private key,
+the handshake will fail.
+
+[cacr2011-goldberg]: https://cacr.uwaterloo.ca/techreports/2011/cacr2011-11.pdf
+
+Circuit extension keys have moderate lifetimes,
+on the order of weeks.
+They are published as part of the directory protocol,
+and relays SHOULD accept handshakes for a while
+after publishing any new key.
+(The exact durations for these are set via
+[a set of network parameters](../param-spec.md#onion-key-rotation-days).)
+
+There are two current kinds of circuit extension keys:
+
+- `KP_ntor`, `KS_ntor`:
+ A curve25519 key
+ used for the [`ntor`](./create-created-cells.md#ntor)
+ and [`ntorv3`](./create-created-cells.md#ntor-v3)
+ circuit extension handshakes.
+
+- `KP_onion_tap`, KS_onion_tap`:
+ A 1024 bit RSA key
+ used for the obsolete [`TAP`](./create-created-cells.md#ntor)
+ circuit extension handshake.
+
+
+## Channel authentication {#auth}
+
+There are other keys that relays use to authenticate
+as part of their [channel negotiation handshakes](./channels.md).
+
+These keys are authenticated with other, longer lived keys.
+Relays MAY rotate them as often as they like,
+and SHOULD rotate them frequently—typically, at least once a day.
+
+<!-- TODO: The following should get revised after I revise the channel
+ handshake distinction. As it stands I'm not at all sure I can
+ describe them correctly. -->
+
+- `KP_legacy_conn_tls`, `KS_legacy_conn_tls`:
+ A short-term RSA "Connection key" used to negotiate TLS connections.
+ Tor implementations MAY rotate this key as often as they like, and
+ SHOULD rotate this key at least once a day.
+
+- `KP_link_ed`, `KS_link_ed`.
+ A short-term Ed25519 "link authentication" key, used to authenticate
+ the link handshake: see
+ ["Negotiating and initializing channels"](./negotiating-channels.md#negotiating).
+ This key is signed by the "signing" key, and should be regenerated frequently.
+
+
+
+
diff --git a/spec/tor-spec/routing-relay-cells.md b/spec/tor-spec/routing-relay-cells.md
index 55520d9..15a5f20 100644
--- a/spec/tor-spec/routing-relay-cells.md
+++ b/spec/tor-spec/routing-relay-cells.md
@@ -29,10 +29,10 @@ When a relay cell is sent from an OP, the OP encrypts the payload
with the stream cipher as follows:
```text
- OP sends relay cell:
- For I=N...1, where N is the destination node:
- Encrypt with Kf_I.
- Transmit the encrypted cell to node 1.
+OP sends relay cell:
+ For I=N...1, where N is the destination node:
+ Encrypt with Kf_I.
+ Transmit the encrypted cell to node 1.
```
<a id="tor-spec.txt-5.5.2.2"></a>
@@ -43,8 +43,8 @@ When a forward relay cell is received by an OR, it decrypts the payload
with the stream cipher, as follows:
```text
- 'Forward' relay cell:
- Use Kf as key; decrypt.
+'Forward' relay cell:
+ Use Kf as key; decrypt.
```
The OR then decides whether it recognizes the relay cell, by
@@ -73,8 +73,8 @@ When a backward relay cell is received by an OR, it encrypts the payload
with the stream cipher, as follows:
```text
- 'Backward' relay cell:
- Use Kb as key; encrypt.
+'Backward' relay cell:
+ Use Kb as key; encrypt.
```
<a id="tor-spec.txt-5.5.3"></a>
@@ -85,10 +85,12 @@ When a relay cell arrives at an OP, the OP decrypts the payload
with the stream cipher as follows:
```text
- OP receives relay cell from node 1:
- For I=1...N, where N is the final node on the circuit:
- Decrypt with Kb_I.
- If the payload is recognized (see section 6.1), then:
- The sending node is I.
- Stop and process the payload.
+OP receives relay cell from node 1:
+ For I=1...N, where N is the final node on the circuit:
+ Decrypt with Kb_I.
+ If the payload is recognized (see [1]), then:
+ The sending node is I.
+ Stop and process the payload.
```
+
+[1]: ["Relay cells"](./relay-cells.md#relay-cells)
diff --git a/spec/tor-spec/setting-circuit-keys.md b/spec/tor-spec/setting-circuit-keys.md
index 6cea0f3..200862f 100644
--- a/spec/tor-spec/setting-circuit-keys.md
+++ b/spec/tor-spec/setting-circuit-keys.md
@@ -4,7 +4,7 @@
<a id="tor-spec.txt-5.2.1"></a>
-## KDF-TOR
+## KDF-TOR{#kdf-tor}
This key derivation function is used by the TAP and CREATE_FAST
handshakes, and in the current hidden service protocol. It shouldn't
@@ -36,7 +36,7 @@ Kb is used to encrypt the stream of data going from the OR to the OP.
<a id="tor-spec.txt-5.2.2"></a>
-## KDF-RFC5869
+## KDF-RFC5869{#kdf-rfc5869}
For newer KDF needs, Tor uses the key derivation function HKDF from
RFC5869, instantiated with SHA256. (This is due to a construction
diff --git a/spec/tor-spec/subprotocol-versioning.md b/spec/tor-spec/subprotocol-versioning.md
index ffd17a6..97c4409 100644
--- a/spec/tor-spec/subprotocol-versioning.md
+++ b/spec/tor-spec/subprotocol-versioning.md
@@ -14,28 +14,26 @@ The dir-spec.txt details how those versions are encoded. See the
Here are the rules a relay and client should follow when encountering a
protocol list in the consensus:
-```text
- - When a relay lacks a protocol listed in recommended-relay-protocols,
- it should warn its operator that the relay is obsolete.
-
- - When a relay lacks a protocol listed in required-relay-protocols, it
- should warn its operator as above. If the consensus is newer than the
- date when the software was released or scheduled for release, it must
- not attempt to join the network.
-
- - When a client lacks a protocol listed in recommended-client-protocols,
- it should warn the user that the client is obsolete.
-
- - When a client lacks a protocol listed in required-client-protocols,
- it should warn the user as above. If the consensus is newer than the
- date when the software was released, it must not connect to the
- network. This implements a "safe forward shutdown" mechanism for
- zombie clients.
-
- - If a client or relay has a cached consensus telling it that a given
- protocol is required, and it does not implement that protocol, it
- SHOULD NOT try to fetch a newer consensus.
-```
+ - When a relay lacks a protocol listed in recommended-relay-protocols,
+ it should warn its operator that the relay is obsolete.
+
+ - When a relay lacks a protocol listed in required-relay-protocols, it
+ should warn its operator as above. If the consensus is newer than the
+ date when the software was released or scheduled for release, it must
+ not attempt to join the network.
+
+ - When a client lacks a protocol listed in recommended-client-protocols,
+ it should warn the user that the client is obsolete.
+
+ - When a client lacks a protocol listed in required-client-protocols,
+ it should warn the user as above. If the consensus is newer than the
+ date when the software was released, it must not connect to the
+ network. This implements a "safe forward shutdown" mechanism for
+ zombie clients.
+
+ - If a client or relay has a cached consensus telling it that a given
+ protocol is required, and it does not implement that protocol, it
+ SHOULD NOT try to fetch a newer consensus.
Software release dates SHOULD be automatically updated as part of the
release process, to prevent forgetting to move them forward. Software
@@ -45,13 +43,15 @@ Starting in version 0.2.9.4-alpha, the initial required protocols for
clients that we will Recommend and Require are:
```text
- Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=4
- LinkAuth=1 Microdesc=1-2 Relay=2
+Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=4
+LinkAuth=1 Microdesc=1-2 Relay=2
+```
- For relays we will Require:
+For relays we will Require:
- Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=3-4
- LinkAuth=1 Microdesc=1 Relay=1-2
+```text
+Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=3-4
+LinkAuth=1 Microdesc=1 Relay=1-2
```
For relays, we will additionally Recommend all protocols which we
@@ -83,11 +83,11 @@ the v3+ link protocols.
Current versions are:
-"1" is the RSA link authentication described in [Link authentication type 1: RSA-SHA256-TLSSecret](./negotiating-channels.md#RSA-SHA256-TLSSecret).
+ * "1" is the RSA link authentication described in [Link authentication type 1: RSA-SHA256-TLSSecret](./negotiating-channels.md#RSA-SHA256-TLSSecret).
-"2" is unused, and reserved by proposal 244.
+ * "2" is unused, and reserved by proposal 244.
-"3" is the ed25519 link authentication described in [Link authentication type 3: Ed25519-SHA256-RFC5705](./negotiating-channels.md#Ed25519-SHA256-RFC5705).
+ * "3" is the ed25519 link authentication described in [Link authentication type 3: Ed25519-SHA256-RFC5705](./negotiating-channels.md#Ed25519-SHA256-RFC5705).
<a id="tor-spec.txt-9.3"></a>
@@ -99,72 +99,71 @@ after a CREATE/CREATE2 cell. (Except, relay cells used to manage
introduction and rendezvous points are managed with the "HSIntro"
and "HSRend" protocols respectively.)
-Current versions are:
+Current versions are as follows.
-```text
- "1" -- supports the TAP key exchange, with all features in Tor 0.2.3.
- Support for CREATE and CREATED and CREATE_FAST and CREATED_FAST
- and EXTEND and EXTENDED.
-
- "2" -- supports the ntor key exchange, and all features in Tor
- 0.2.4.19. Includes support for CREATE2 and CREATED2 and
- EXTEND2 and EXTENDED2.
-
- Relay=2 has limited IPv6 support:
- * Clients might not include IPv6 ORPorts in EXTEND2 cells.
- * Relays (and bridges) might not initiate IPv6 connections in
- response to EXTEND2 cells containing IPv6 ORPorts, even if they
- are configured with an IPv6 ORPort.
-
- However, relays support accepting inbound connections to their IPv6
- ORPorts. And they might extend circuits via authenticated IPv6
- connections to other relays.
-
- "3" -- relays support extending over IPv6 connections in response to an
- EXTEND2 cell containing an IPv6 ORPort.
-
- Bridges might not extend over IPv6, because they try to imitate
- client behaviour.
-
- A successful IPv6 extend requires:
- * Relay subprotocol version 3 (or later) on the extending relay,
- * an IPv6 ORPort on the extending relay,
- * an IPv6 ORPort for the accepting relay in the EXTEND2 cell, and
- * an IPv6 ORPort on the accepting relay.
- (Because different tor instances can have different views of the
- network, these checks should be done when the path is selected.
- Extending relays should only check local IPv6 information, before
- attempting the extend.)
-
- When relays receive an EXTEND2 cell containing both an IPv4 and an
- IPv6 ORPort, and there is no existing authenticated connection with
- the target relay, the extending relay may choose between IPv4 and
- IPv6 at random. The extending relay might not try the other address,
- if the first connection fails.
-
- As is the case with other subprotocol versions, tor advertises,
- recommends, or requires support for this protocol version, regardless
- of its current configuration.
-
- In particular:
- * relays without an IPv6 ORPort, and
- * tor instances that are not relays,
- have the following behaviour, regardless of their configuration:
- * advertise support for "Relay=3" in their descriptor
- (if they are a relay, bridge, or directory authority), and
- * react to consensuses recommending or requiring support for
- "Relay=3".
-
- This subprotocol version is described in proposal 311, and
- implemented in Tor 0.4.5.1-alpha.
-
- "4" -- support the ntorv3 (version 3) key exchange and all features in
- 0.4.7.3-alpha. This adds a new CREATE2 cell type. See proposal 332
- and section 5.1.4.1 above for more details.
-
- "5" -- [RESERVED] support the ntorv3 subprotocol request extension (prop346)
- allowing a client to request what features to be used on a circuit.
-```
+ * "1" -- supports the TAP key exchange, with all features in Tor 0.2.3.
+ Support for CREATE and CREATED and CREATE_FAST and CREATED_FAST
+ and EXTEND and EXTENDED.
+
+ * "2" -- supports the ntor key exchange, and all features in Tor
+ 0.2.4.19. Includes support for CREATE2 and CREATED2 and
+ EXTEND2 and EXTENDED2.
+
+ Relay=2 has limited IPv6 support:
+
+ * Clients might not include IPv6 ORPorts in EXTEND2 cells.
+ * Relays (and bridges) might not initiate IPv6 connections in
+ response to EXTEND2 cells containing IPv6 ORPorts, even if they
+ are configured with an IPv6 ORPort.
+
+ However, relays support accepting inbound connections to their IPv6
+ ORPorts. And they might extend circuits via authenticated IPv6
+ connections to other relays.
+
+ * "3" -- relays support extending over IPv6 connections in response to an
+ EXTEND2 cell containing an IPv6 ORPort.
+
+ Bridges might not extend over IPv6, because they try to imitate
+ client behaviour.
+
+ A successful IPv6 extend requires:
+ * Relay subprotocol version 3 (or later) on the extending relay,
+ * an IPv6 ORPort on the extending relay,
+ * an IPv6 ORPort for the accepting relay in the EXTEND2 cell, and
+ * an IPv6 ORPort on the accepting relay.
+ (Because different tor instances can have different views of the
+ network, these checks should be done when the path is selected.
+ Extending relays should only check local IPv6 information, before
+ attempting the extend.)
+
+ When relays receive an EXTEND2 cell containing both an IPv4 and an
+ IPv6 ORPort, and there is no existing authenticated connection with
+ the target relay, the extending relay may choose between IPv4 and
+ IPv6 at random. The extending relay might not try the other address,
+ if the first connection fails.
+
+ As is the case with other subprotocol versions, tor advertises,
+ recommends, or requires support for this protocol version, regardless
+ of its current configuration.
+
+ In particular:
+ * relays without an IPv6 ORPort, and
+ * tor instances that are not relays,
+ have the following behaviour, regardless of their configuration:
+ * advertise support for "Relay=3" in their descriptor
+ (if they are a relay, bridge, or directory authority), and
+ * react to consensuses recommending or requiring support for
+ "Relay=3".
+
+ This subprotocol version is described in proposal 311, and
+ implemented in Tor 0.4.5.1-alpha.
+
+ * "4" -- support the ntorv3 (version 3) key exchange and all features in
+ 0.4.7.3-alpha. This adds a new CREATE2 cell type. See proposal 332
+ and [The "ntor-v3" handshake](./create-created-cells.md#ntor-v3) for more details.
+
+ * "5" -- [RESERVED] support the ntorv3 subprotocol request extension (prop346)
+ allowing a client to request what features to be used on a circuit.
<a id="tor-spec.txt-9.4"></a>
@@ -172,16 +171,14 @@ Current versions are:
The "HSIntro" protocol handles introduction points.
-```text
- "3" -- supports authentication as of proposal 121 in Tor
- 0.2.1.6-alpha.
+ * "3" -- supports authentication as of proposal 121 in Tor
+ 0.2.1.6-alpha.
- "4" -- support ed25519 authentication keys which is defined by the HS v3
- protocol as part of proposal 224 in Tor 0.3.0.4-alpha.
+ * "4" -- support ed25519 authentication keys which is defined by the HS v3
+ protocol as part of proposal 224 in Tor 0.3.0.4-alpha.
- "5" -- support ESTABLISH_INTRO cell DoS parameters extension for onion
- service version 3 only in Tor 0.4.2.1-alpha.
-```
+ * "5" -- support ESTABLISH_INTRO cell DoS parameters extension for onion
+ service version 3 only in Tor 0.4.2.1-alpha.
<a id="tor-spec.txt-9.5"></a>
@@ -189,12 +186,10 @@ The "HSIntro" protocol handles introduction points.
The "HSRend" protocol handles rendezvous points.
-"1" -- supports all features in Tor 0.0.6.
+ * "1" -- supports all features in Tor 0.0.6.
-```text
- "2" -- supports RENDEZVOUS2 cells of arbitrary length as long as they
- have 20 bytes of cookie in Tor 0.2.9.1-alpha.
-```
+ * "2" -- supports RENDEZVOUS2 cells of arbitrary length as long as they
+ have 20 bytes of cookie in Tor 0.2.9.1-alpha.
<a id="tor-spec.txt-9.6"></a>
@@ -204,12 +199,10 @@ The "HSDir" protocols are the set of hidden service document types that can
be uploaded to, understood by, and downloaded from a tor relay, and the set
of URLs available to fetch them.
-"1" -- supports all features in Tor 0.2.0.10-alpha.
+ * "1" -- supports all features in Tor 0.2.0.10-alpha.
-```text
- "2" -- support ed25519 blinded keys request which is defined by the HS v3
- protocol as part of proposal 224 in Tor 0.3.0.4-alpha.
-```
+ * "2" -- support ed25519 blinded keys request which is defined by the HS v3
+ protocol as part of proposal 224 in Tor 0.3.0.4-alpha.
<a id="tor-spec.txt-9.7"></a>
@@ -219,9 +212,9 @@ The "DirCache" protocols are the set of documents available for download
from a directory cache via BEGIN_DIR, and the set of URLs available to
fetch them. (This excludes URLs for hidden service objects.)
-"1" -- supports all features in Tor 0.2.4.19.
+ * "1" -- supports all features in Tor 0.2.4.19.
-"2" -- adds support for consensus diffs in Tor 0.3.1.1-alpha.
+ * "2" -- adds support for consensus diffs in Tor 0.3.1.1-alpha.
<a id="tor-spec.txt-9.8"></a>
@@ -233,9 +226,9 @@ Most features in descriptors don't require a "Desc" update -- only those
that need to someday be required. For example, someday clients will need
to understand ed25519 identities.
-"1" -- supports all features in Tor 0.2.4.19.
+ * "1" -- supports all features in Tor 0.2.4.19.
-"2" -- cross-signing with onion-keys, signing with ed25519
+ * "2" -- cross-signing with onion-keys, signing with ed25519
identities.
<a id="tor-spec.txt-9.9"></a>
@@ -248,9 +241,9 @@ Most features in descriptors don't require a "MicroDesc" update -- only
those that need to someday be required. These correspond more or less with
consensus methods.
-"1" -- consensus methods 9 through 20.
+ * "1" -- consensus methods 9 through 20.
-"2" -- consensus method 21 (adds ed25519 keys to microdescs).
+ * "2" -- consensus method 21 (adds ed25519 keys to microdescs).
<a id="tor-spec.txt-9.10"></a>
@@ -263,9 +256,9 @@ those that need to someday be required.
These correspond more or less with consensus methods.
-"1" -- consensus methods 9 through 20.
+ * "1" -- consensus methods 9 through 20.
-"2" -- consensus method 21 (adds ed25519 keys to microdescs).
+ * "2" -- consensus method 21 (adds ed25519 keys to microdescs).
<a id="tor-spec.txt-9.11"></a>
@@ -273,15 +266,13 @@ These correspond more or less with consensus methods.
Describes the padding capabilities of the relay.
-```text
- "1" -- [DEFUNCT] Relay supports circuit-level padding. This version MUST NOT
- be used as it was also enabled in relays that don't actually support
- circuit-level padding. Advertised by Tor versions from
- tor-0.4.0.1-alpha and only up to and including tor-0.4.1.4-rc.
+ * "1" -- [DEFUNCT] Relay supports circuit-level padding. This version MUST NOT
+ be used as it was also enabled in relays that don't actually support
+ circuit-level padding. Advertised by Tor versions from
+ tor-0.4.0.1-alpha and only up to and including tor-0.4.1.4-rc.
- "2" -- Relay supports the HS circuit setup padding machines (proposal 302).
- Advertised by Tor versions from tor-0.4.1.5 and onwards.
-```
+ * "2" -- Relay supports the HS circuit setup padding machines (proposal 302).
+ Advertised by Tor versions from tor-0.4.1.5 and onwards.
<a id="tor-spec.txt-9.12"></a>
@@ -291,14 +282,12 @@ Describes the flow control protocol at the circuit and stream level. If
there is no FlowCtrl advertised, tor supports the unauthenticated flow
control features (version 0).
-```text
- "1" -- supports authenticated circuit level SENDMEs as of proposal 289 in
- Tor 0.4.1.1-alpha.
+ * "1" -- supports authenticated circuit level SENDMEs as of proposal 289 in
+ Tor 0.4.1.1-alpha.
- "2" -- supports congestion control by the Exits which implies a new SENDME
- format and algorithm. See proposal 324 for more details. Advertised
- in tor 0.4.7.3-alpha.
-```
+ * "2" -- supports congestion control by the Exits which implies a new SENDME
+ format and algorithm. See proposal 324 for more details. Advertised
+ in tor 0.4.7.3-alpha.
## "Conflux"
@@ -314,8 +303,6 @@ in order to split traffic across multiple paths.
Describes the UDP protocol capabilities of a relay.
-```text
- "1" -- [RESERVED] supports UDP by an Exit as in the relay command
- CONNECT_UDP, CONNECTED_UDP and DATAGRAM. See proposal
- 339 for more details. (Not yet advertised, reserved)
-```
+ * "1" -- [RESERVED] supports UDP by an Exit as in the relay command
+ CONNECT_UDP, CONNECTED_UDP and DATAGRAM. See proposal
+ 339 for more details. (Not yet advertised, reserved)
diff --git a/spec/tor-spec/system-overview.md b/spec/tor-spec/system-overview.md
index f05b893..17cc1a4 100644
--- a/spec/tor-spec/system-overview.md
+++ b/spec/tor-spec/system-overview.md
@@ -8,64 +8,3 @@ and instant messaging. Clients choose a path through the network and
build a `circuit'', in which each node (or`onion router'' or `OR'') in the path knows its predecessor and successor, but no other nodes in the circuit. Traffic flowing down the circuit is sent in fixed-size `cells'', which are unwrapped by a symmetric key at each node (like
the layers of an onion) and relayed downstream.
-<a id="tor-spec.txt-1.1"></a>
-
-## Keys and names
-
-Every Tor relay has multiple public/private keypairs:
-
-These are 1024-bit RSA keys:
-
-```text
- - A long-term signing-only "Identity key" used to sign documents and
- certificates, and used to establish relay identity.
- KP_relayid_rsa, KS_relayid_rsa.
- - A medium-term TAP "Onion key" used to decrypt onion skins when accepting
- circuit extend attempts. (See 5.1.) Old keys MUST be accepted for a
- while after they are no longer advertised. Because of this,
- relays MUST retain old keys for a while after they're rotated. (See
- "onion key lifetime parameters" in dir-spec.txt.)
- KP_onion_tap, KS_onion_tap.
- - A short-term "Connection key" used to negotiate TLS connections.
- Tor implementations MAY rotate this key as often as they like, and
- SHOULD rotate this key at least once a day.
- KP_conn_tls, KS_conn_tls.
-
- This is Curve25519 key:
-
- - A medium-term ntor "Onion key" used to handle onion key handshakes when
- accepting incoming circuit extend requests. As with TAP onion keys,
- old ntor keys MUST be accepted for at least one week after they are no
- longer advertised. Because of this, relays MUST retain old keys for a
- while after they're rotated. (See "onion key lifetime parameters" in
- dir-spec.txt.)
- KP_ntor, KS_ntor.
-
- These are Ed25519 keys:
-
- - A long-term "master identity" key. This key never
- changes; it is used only to sign the "signing" key below. It may be
- kept offline.
- KP_relayid_ed, KS_relayid_ed.
- - A medium-term "signing" key. This key is signed by the master identity
- key, and must be kept online. A new one should be generated
- periodically. It signs nearly everything else.
- KP_relaysign_ed, KS_relaysign_ed.
- - A short-term "link authentication" key, used to authenticate
- the link handshake: see section 4 below. This key is signed
- by the "signing" key, and should be regenerated frequently.
- KP_link_ed, KS_link_ed.
-```
-
-KP_relayid\_\* together identify a router uniquely. Once a router
-has used a KP_relayid_ed (an Ed25519 master identity key)
-together with a given KP_relayid_rsa (RSA identity key), neither of
-those keys may ever be used with a different key.
-
-We write KP_relayid to refer to a key which is either
-KP_relayid_rsa or KP_relayid_ed.
-
-The same key or keypair should never be used for separate roles within
-the Tor protocol suite, unless specifically stated. For example,
-a relay's identity keys K_relayid should not also be used as the
-identity keypair for a hidden service K_hs_id (see rend-spec-v3.txt).