diff options
author | Nick Mathewson <nickm@torproject.org> | 2023-11-11 21:57:53 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2023-11-11 22:05:07 -0500 |
commit | 46f947115f4cce14b7b2368a414c765fc18e86b4 (patch) | |
tree | b0c69346efa722a145ed9bcb6e88a96c489880dd | |
parent | a602166da2fffe55e882dd7879ecd82994996a45 (diff) | |
download | torspec-46f947115f4cce14b7b2368a414c765fc18e86b4.tar.gz torspec-46f947115f4cce14b7b2368a414c765fc18e86b4.zip |
Finish revising the channel handshake
-rw-r--r-- | spec/tor-spec/negotiating-channels.md | 280 | ||||
-rw-r--r-- | spec/tor-spec/obsolete-channels.md | 53 | ||||
-rw-r--r-- | spec/tor-spec/preliminaries.md | 2 | ||||
-rw-r--r-- | spec/tor-spec/subprotocol-versioning.md | 2 |
4 files changed, 211 insertions, 126 deletions
diff --git a/spec/tor-spec/negotiating-channels.md b/spec/tor-spec/negotiating-channels.md index cf559a4..dfe82df 100644 --- a/spec/tor-spec/negotiating-channels.md +++ b/spec/tor-spec/negotiating-channels.md @@ -265,7 +265,6 @@ then any relay which can prove it has the the identity `KP_relayid_ed` also has the legacy identity `KP_relayid_rsa`. - <a id="tor-spec.txt-4.3"></a> ## AUTH_CHALLENGE cells{#AUTH-CHALLENGE-cells} @@ -279,157 +278,158 @@ fields: | 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 -generate every challenge independently using a strong RNG or PRNG. +It is sent from the responder to the initiator. +Initiators MUST ignore unexpected bytes at the end of the cell. +Responders MUST generate every challenge independently. + +The Challenge field is +a [randomly generated](./preliminaries.md#random-values) +binary string that the initiator must sign (a hash of) +as part of their [AUTHENTICATE cell](#AUTHENTICATE-cells). + +The Methods are a list of authentication methods +that the responder will accept. +These methods are defined: + +| Type | Method | +| --------- | ------ | +| `[00 01]` | [RSA-SHA256-TLSSecret] (Obsolete) | +| `[00 02]` | (Historical, never implemented) | +| `[00 03]` | [Ed25519-SHA256-RFC5705] | + -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 [RSA-SHA256-TLSSecret](#RSA-SHA256-TLSSecret) and -[Ed25519-SHA256-RFC570](#Ed25519-SHA256-RFC5705) below. +[RSA-SHA256-TLSSecret]: ./obsolete-channels.md#RSA-SHA256-TLSSecret +[Ed25519-SHA256-RFC5705]: #Ed25519-SHA256-RFC5705 <a id="tor-spec.txt-4.4"></a> ## AUTHENTICATE cells{#AUTHENTICATE-cells} -If an initiator wants to authenticate, it responds to the -AUTH_CHALLENGE cell with a CERTS cell and an AUTHENTICATE cell. -The CERTS cell is as a server would send, except that instead of -sending a CertType 1 (and possibly CertType 5) certs for arbitrary link -certificates, the initiator sends a CertType 3 (and possibly -CertType 6) cert for an RSA/Ed25519 AUTHENTICATE key. +If an initiator wants to authenticate, +it responds to the AUTH_CHALLENGE cell +with a CERTS cell and an AUTHENTICATE cell. -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 -[RSA-SHA256-TLSSecret](#RSA-SHA256-TLSSecret) and -[Ed25519-SHA256-RFC570](#Ed25519-SHA256-RFC5705) below. +([As discussed above](#validate-initiator-certs), +the initiator's CERTS cell differs slightly +from what a responder would send.) An AUTHENTICATE cell contains the following: | Field | Size | ----- | ---- -| AuthType | 2 octets -| AuthLen | 2 octets -| Authentication | AuthLen octets +| AuthType | 2 +| AuthLen | 2 +| Authentication | AuthLen Responders MUST ignore extra bytes at the end of an AUTHENTICATE -cell. Recognized AuthTypes are 1 and 3, described in the next -two sections. - -Initiators MUST NOT send an AUTHENTICATE cell before they have -verified the certificates presented in the responder's CERTS -cell, and authenticated the responder. - -<a id="tor-spec.txt-4.4.1"></a> - -### Link authentication type 1: RSA-SHA256-TLSSecret {#RSA-SHA256-TLSSecret} - -If AuthType is 1 (meaning "RSA-SHA256-TLSSecret"), then the -Authentication field of the AUTHENTICATE cell contains the following: - -* 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 -correct values as described above, and then verifies the signature. -The server MUST ignore any extra bytes in the signed data after -the RAND field. +cell. -Responders MUST NOT accept this AuthType if the initiator has -claimed to have an Ed25519 identity. +The `AuthType` value corresponds to one of the +authentication methods. +The initiator MUST NOT send an AUTHENTICATE cell +whose AuthType was not contained +in the responder's AUTH_CHALLENGE. -(There is no AuthType 2: It was reserved but never implemented.) +An initiator MUST NOT send an AUTHENTICATE +cell before it has verified the certificates +presented in the responder's CERTS cell, +and authenticated the responder. <a id="tor-spec.txt-4.4.2"></a> ### Link authentication type 3: Ed25519-SHA256-RFC5705 {#Ed25519-SHA256-RFC5705} -If AuthType is 3, meaning "Ed25519-SHA256-RFC5705", the -Authentication field of the AuthType cell is as below: +If AuthType is `[00 03]`, +meaning "Ed25519-SHA256-RFC5705", +the Authentication field of the AUTHENTICE cell is as follows Modified values and new fields below are marked with asterisks. -* 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 -correct values as described above, and then verifies the signature. -The server MUST ignore any extra bytes in the signed data after +| Field | Size | Description | +| --------- | ---- | ----------- | +| `TYPE` | 8 | The nonterminated string `AUTH0003` | +| `CID` | 32 | `SHA256(KP_relayid_rsa)` for initiator | +| `SID` | 32 | `SHA256(KP_relayid_rsa)` for responder | +| `CID_ED` | 32 | `KP_relayid_ed` for initiator | +| `SID_ED` | 32 | `KP_relayid_ed` for responder | +| `SLOG` | 32 | SHA256 of responder transcript | +| `CLOG` | 32 | SHA256 of initiator transcript | +| `SCERT` | 32 | SHA256 of responder's TLS certificate | +| `TLSSECRETS`|32 | RFC5705 information | +| `RAND` | 24 | [Random bytes] | +| `SIG` | 64 | Ed25519 signature | + +Notes: + +- For `CID` and `SID`, the SHA256 digest of an RSA key + is computed as the SHA256 digest of its asn.1 encoding. +- The `SLOG` field is computed + as the SHA256 digest + of all bytes sent within the TLS channel up to and including + the AUTH_CHALLENGE cell. + - This includes the VERSIONS cell, + the CERTS cell, + the AUTH_CHALLENGE cell, + and any padding cells. +- The `CLOG` field is computed + as the SHA256 digest + of all bytes sent within the TLS channel up to but not including + the AUTHENTICATE cell. + - This includes the VERSIONS cell, + the CERTS cell, and any padding cells. +- The `TLSSECRETS` field is computed + as the output of a Keying Material Exporter function + on the TLS section. + - The parameters for this exporter are: + - Label string: "EXPORTER FOR TOR TLS CLIENT BINDING AUTH0003" + - Context value: The initiator's `KP_relayid_ed`. + - Length: 32. + - For keying material exporters on TLS 1.3, + see [RFC 8446 Section 7.5]. + - For keying material exporters on older TLS versions, + see [RFC5705]. +- The `SIG` field is an Ed25519 signature + of all earlier members in the Authentication + (from `TYPE` through `RAND`) + using `KS_link_ed`. + + +[Random bytes]: ./preliminaries.md#random-values +[RFC 8446 Section 7.5]: https://datatracker.ietf.org/doc/html/rfc8446#section-7.5 +[RFC5705]: https://datatracker.ietf.org/doc/html/rfc5705. + + +To check an AUTHENTICATE cell, +a responder checks that all fields from TYPE through TLSSECRETS +contain their unique correct values as described above, +and then verifies the signature. +The responder MUST ignore any extra bytes in the signed data after the RAND field. +<!-- TODO: We should consider removing that last sentence. --> + <a id="tor-spec.txt-4.5"></a> ## NETINFO cells {#NETINFO-cells} -If version 2 or higher is negotiated, each party sends the other a -NETINFO cell. The cell's payload is: +To finish the handshake, +each party sends the other +a NETINFO cell. + +The cell's payload is: | Field | Description | Size | ----- | ----------- | ---- | TIME | Timestamp | 4 bytes -| OTHERADDR: | Other OR's address | +| OTHERADDR: | Other party'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 +| - AVAL | Address value | ALEN bytes +| NMYADDR | Number of this party's addresses | 1 byte | NMYADDR times: | | | - ATYPE | Address type | 1 byte | - ALEN | Address length | 1 byte -| - AVAL | Address value in NBO | ALEN bytes +| - AVAL | Address value | ALEN bytes Recognized address types (ATYPE) are: @@ -438,22 +438,52 @@ Recognized address types (ATYPE) are: | 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 +Implementations SHOULD ignore addresses with unrecognized types. + +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 the provided address should be ignored. -The timestamp is a big-endian unsigned integer number of seconds -since the Unix epoch. Implementations MUST ignore unexpected bytes -at the end of the cell. Clients SHOULD send "0" as their timestamp, to -avoid fingerprinting. +When sending `OTHERADDR`, +implementations SHOULD use the actual IP address +they have observed for the other party. + +> (This is typically the address passed to `connect()` +> when acting as the channel initiator, +> or the address received from `accept()` +> when acting as the channel responder.) + +When sending the party's own addresses, +relays SHOULD send the addresses that they have advertised +in their router descriptors. +Bridges and clients SHOULD send none of their own addresses. + +For the `TIME` field, +relays send a (big-endian) integer +holding the number of seconds since the Unix epoch. +Clients SHOULD send `[00 00 00 00]` as their timestamp, +to avoid fingerprinting. + +> See [proposal 338](../proposals/338-netinfo-y2038.md) +> for a proposal to extend the timestamp to 8 bytes. + +Implementations MUST ignore unexpected bytes at the end of the NETINFO cell. + +### Using information from NETINFO cells {#using-netinfo} Implementations MAY use the timestamp value to help decide if their -clocks are skewed. Initiators MAY use "other OR's address" to help -learn which address their connections may be originating from, if they do -not know it; and to learn whether the peer will treat the current -connection as canonical. Implementations SHOULD NOT trust these -values unconditionally, especially when they come from non-authorities, -since the other party can lie about the time or IP addresses it sees. +clocks are skewed. + +Initiators MAY use "other OR's address" field +to help learn which address their connections may be originating from, +if they do not know it; +and to learn whether the peer will treat the current connection as canonical. + +Implementations SHOULD NOT trust these values unconditionally, +especially when they come from non-authorities, +since the other party can lie about the time +or the 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. diff --git a/spec/tor-spec/obsolete-channels.md b/spec/tor-spec/obsolete-channels.md index 33874d4..52e716f 100644 --- a/spec/tor-spec/obsolete-channels.md +++ b/spec/tor-spec/obsolete-channels.md @@ -214,3 +214,56 @@ it would need to verify that: not expired, and not before their `validAfter` dates. + +<a id="tor-spec.txt-4.4.1"></a> + +## Link authentication type 1: RSA-SHA256-TLSSecret {#RSA-SHA256-TLSSecret} + +This is an obsolete authentication method +used before RFC5705 support was ubiquitous. +It is nearly the same as +[Ed25519-SHA256-RFC5705](./negotiating-channels.md#Ed25519-SHA256-RFC5705), +but lacks support for Ed25519, +and does not use keying material exporters +(which were not widely supported at the time it as used. + +If AuthType is `[00 01]` (meaning "RSA-SHA256-TLSSecret"), +then the authentication field of the AUTHENTICATE +cell contains the following: + +| Field | Size | Description | +| --------- | ---- | ----------- | +| `TYPE` | 8 | The nonterminated string `AUTH0001` | +| `CID` | 32 | `SHA256(KP_relayid_rsa)` for initiator | +| `SID` | 32 | `SHA256(KP_relayid_rsa)` for responder | +| `SLOG` | 32 | SHA256 of responder transcript | +| `CLOG` | 32 | SHA256 of initiator transcript | +| `SCERT` | 32 | SHA256 of responder's TLS certificate | +| `TLSSECRETS`|32 | An ad-hoc HMAC output | +| `RAND` | 24 | [Random bytes] | +| `SIG` | Variable | RSA signature | + + +Notes are as for [Ed25519-SHA256-RFC5705], +except as follows: + + +- The `TLSSECRETS` fields holds a SHA256 HMAC, + using the TLS master secret as the secret key, + of the following concatenated fields: + - `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"` +* The `SIG` fields holds an RSA signature of a SHA256 hash + of all the previous fields + (that is, `TYPE` through `RAND`), + using the initiator's `KS_legacy_linkauth_rsa`. + This field extends through the end of the Authenticate message. + +[Random bytes]: ./preliminaries.md#random-values +[Ed25519-SHA256-RFC5705]: ./negotiating-channels.md#Ed25519-SHA256-RFC5705 + +Responders MUST NOT accept this AuthType if the initiator has +claimed to have an Ed25519 identity. + diff --git a/spec/tor-spec/preliminaries.md b/spec/tor-spec/preliminaries.md index 78e6e80..b8e558f 100644 --- a/spec/tor-spec/preliminaries.md +++ b/spec/tor-spec/preliminaries.md @@ -107,9 +107,11 @@ When we refer to "the hash of a public key", unless otherwise specified, we mean the SHA-1 hash of the DER encoding of an ASN.1 RSA public key (as specified in PKCS.1). +<span id="random-values"> All "random" values MUST be generated with a cryptographically strong pseudorandom number generator seeded from a strong entropy source, unless otherwise noted. +</span> <a id="tor-spec.txt-0.4"></a> diff --git a/spec/tor-spec/subprotocol-versioning.md b/spec/tor-spec/subprotocol-versioning.md index 82b25c4..c9a9c76 100644 --- a/spec/tor-spec/subprotocol-versioning.md +++ b/spec/tor-spec/subprotocol-versioning.md @@ -83,7 +83,7 @@ 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](./obsolete-channels.md#RSA-SHA256-TLSSecret). * "2" is unused, and reserved by proposal 244. |