123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397 |
- This file aims to document the low-level details of communication and protocol
- in Ricochet.
- Unless otherwise noted, this document describes protocol version 0. Section 1
- (protocol negotiation) is intended to be invariant, as it is responsible for
- negotiating the protocol version.
- Table of contents:
- 0. Conventions in this document
- 1. The hidden service layer
- 2. Protocol negotiation
- 2.1. Introduction syntax
- 3. Connection purpose and authentication
- 3.1. Authenticated contact connections
- 4. Connection management
- 4.1. Command connections
- 4.2. Data connections
- 5. Message processing
- 6. Commands and replies
- 6.1. Length field
- 6.2. Command field
- 6.3. State field
- 6.4. Identifier field
- 6.5. Data
- 7. Defined commands
- 7.1. 0x00 - Ping
- 7.2. 0x01 - Get connection secret
- 7.3. 0x10 - Chat message
- 8. Contact request connections
- 0. Conventions in this document
- 'Client' refers to the peer creating the connection
- 'Server' refers to the peer receiving an incoming connection. After
- authentication, this distinction is irrelevant.
- 1. The hidden service layer
- [TBD: describe use of hidden services and the properties they make available]
- Connections are made to port 9878 of the hidden service.
- 2. Protocol negotiation
- Immediately after establishing a connection, the client must send an
- introduction. The server is expected to expire any connection on which
- this introduction does not arrive in a reasonable amount of time.
- 2.1. Introduction syntax
- The client must send the following sequence:
- 0x49
- 0x4D
- nVersions [1 octet]
- versions [nVersions bytes]
- 'nVersions' describes the number of version fields to follow. Each version
- field is a single octet, where each value identifies an incompatible
- protocol. The value 0xFF is reserved to indicate failure in a later reply.
- In response, once the entire introduction has been received, the server
- responds with a single octet containing the protocol version chosen from
- the list provided by the client. This should be the highest mutually
- supported version. If there is no mutual version, the server sends 0xff
- (which is not a valid version value), and terminates the connection.
- Implementations MUST NOT expect any more than 4 octets (the introduction
- with one version) to arrive before attempting to process them. The client
- MUST NOT expect more than one octet (the response version) before
- processing that data, regardless of any data which may immediately follow.
- 3. Connection purpose and authentication
- Immediately after version negotiation has finished (i.e. the server has
- responded), the client must send a connection purpose field, which defines
- the type of connection. This is a single octet, with the following
- currently recognized values:
- 0x00 Contact command connection
- 0x01 Contact data connection
- 0x80 Contact request
- Any value below 0x20 (non-inclusive) shares the same immediate usage for
- authentication. The 0x00 value indicates a command connection (4.),
- while all others are auxiliary connections. The protocol version must be
- increased when introducing a new purpose.
- 3.1. Authenticated contact connections
- For connections with a purpose value below 0x20, the following
- authentication process is used to prove the identity of existing
- contacts.
- After sending the purpose, the client must follow with a 16-octet
- pre-exchanged secret. This secret is specific to each peer, and is defined
- during the contact request (or shortly thereafter). Because of the
- hidden service layer pre-authenticating the server end of the connection,
- and the existing layers of encryption, this value is sent in plaintext.
- The server looks up this value and matches it to any known contacts.
- It then sends a one-octet response code; the value 0x00 for this code
- indicates success, while all other values are assumed to be failure.
- Any failure response may be followed by the server immediately closing
- the connection, or may be followed by additional information. No response
- other than 0x00 will result in the connection continuing to exist. The
- following responses are currently defined:
- 0x00 Success
- 0x01 General failure; immediately closes the connection
- 0x02 Unrecognized secret
- After a success reply, the connection transitions into message parsing
- and may be used bidirectionally as desired. The "unrecognized secret"
- response should be considered a permanent failure and disable future
- connection attempts without issuing a new contact request.
- 4. Connection management
- 4.1. Command connections
- Connections initiated with a purpose of 0x00 (see section 3.) are command
- connections, over which the protocol defined in section 5 through 7 is
- used. Generally, there may only be one command connection with a peer,
- and a new connection is considered to replace any existing connection
- (causing failure of all incomplete commands).
- A race is possible when two peers connect simultaniously and each
- establish a command connection. To resolve this situation, the following
- rules are used:
- - If the remote peer establishes a command connection prior to
- sending authentication data for an outgoing attempt, the outgoing
- attempt is aborted and the peer's connection is used.
- - If the existing connection is more than 30 seconds old, measured
- from the time authentication is sent, it is replaced and closed.
- - Otherwise, both peers close the connection for which the server's
- onion-formatted hostname is considered less by a strcmp function.
- 4.2. Data connections
- All commands and general communication take place over the command
- connection. It's important that command connections keep low latency
- regardless of throughput, so they are not suitable for transferring
- large data.
- Peers may establish data connections with a purpose of 0x01 for the
- transfer of larger amounts of data. These transfers must first be
- negotiated on the command connection, where the receiving peer assigns
- a 4 octet identifier for the blob of data.
- Either peer may use a data connection regardless of why it was
- originally established. Connections should not be closed by expiration
- if a pending identifier has been issued for the peer's use. It should
- be possible for the sending peer in a transfer to indicate that the
- recipient should establish a data connection, to avoid relying on
- the connectivity of both peers.
- Data arrives in the following form:
- identifier [4 octets]
- length [64-bit unsigned big endian integer]
- data [length octets]
- Unexpected identifiers may be ignored or result in closing the
- data connection.
- 5. Message processing
- Most communication takes place over the command or message protocol, used
- on authenticated connections with contacts. This is a sequence of messages,
- each of which is a command or a reply.
- All commands must generate a reply, unless otherwise specifically defined.
- This is done to allow intelligent handling of various error situations, and
- to enable better internal API for managing outstanding commands. Replies
- have a concept of finality; a command may generate many replies, but must
- have exactly one final reply, which obviously must be the last.
- Each command also has an identifier; this is a 16-bit value unique to the
- sender of the command, which serves to relate replies back to the original
- command. As a result of this, there is no requirement that replies be
- immediate, and they may even be interleaved with other replies. The
- identifier may be considered unused immediately after a final reply arrives
- with that identifier set. Identifiers are specific to a single connection.
- 0 is reserved for identifiers, and should not be used.
- One last distinction is between two types of messages that have very
- different behavior for processing. Buffered messages (which are the
- majority) include their length, which may not exceed 65,540 octets
- inclusive of the header and the length itself, meaning that they may
- have a maximum payload of 65,534 octets. As the name implies, buffered
- messages are buffered until all data has arrived, and processed once.
- 6. Commands and replies
- The syntax of a message (a command or reply) is:
- length [16-bit big endian integer]
- command [1 octet]
- state [1 octet]
- identifier [16-bit big endian integer]
- data [length-1 octets, or unspecified]
- These fields will be addressed in order.
- 6.1. Length field
- The length is a 16-bit big endian integer defining the size in bytes of the
- data payload in the message. This length does not include the header of the
- message. It may be 0 for messages with no associated data.
- 6.2. Command field
- The command is a one octet identifier for the command that should be
- performed. When adding commands, great care should be taken to avoid
- collisions with any other implementation. Command values below 0x80 should
- be reserved for definition in this official document, while those above
- are open for third party usage with appropriate precautions. A feature
- inspection command may be introduced in the future to handle this issue.
- For details on existing commands, see section 7.
- 6.3. State field
- The state field can be thought of as a subdivision of the command. It
- enables different usages of the same command, and is also used to indicate
- replies and reply status. The state is one octet, which is to be
- interpreted as follows, where 0 is the most significant bit (0x80), and 7
- is the least significant (0x01).
- Bit 0 (0x80) indicates if the message is a reply.
- If bit 0 is NOT set, the message is a command:
- Bit 1 (0x40) is reserved, and should have a value of 1.
- Bits 2 through 7 are available for command-specific usage.
- If bit 0 IS set:
- Bit 1 (0x40) indicates if the reply is a final reply. No more replies
- may arrive with the same identifier for that command after the final
- reply.
- Bit 2 (0x20) indicates if the command was successful. This bit should
- be set for any reply which does not indicate failure, but is largely
- intepreted by the command itself.
- IF bit 2 is NOT set (i.e. the command failed), all values with bit 3
- (0x10) set are reserved for protocol usage as defined below.
- All other bits (3-7 for success, 4-7 for failure) are available for
- command-specific usage.
- The following chart describes these values and their meaning:
- 0x00 to 0x3F Reserved (unused)
- 0x40 to 0x7F Command
- 0x80 to 0x8F Reply Intermediate Failure Available
- 0x90 to 0x9F Reply Intermediate Failure Reserved
- 0xA0 to 0xBF Reply Intermediate Successful
- 0xC0 to 0xCF Reply Final Failure Available
- 0xD0 to 0xDF Reply Final Failure Reserved
- 0xE0 to 0xFF Reply Final Successful
- 6.4. Identifier field
- The identifier is a 16-bit big endian integer, selected when sending the
- command. It is unique to the peer and connection. It is illegal to send a
- command with the same identifier as a command for which a final reply has
- not arrived. It is illegal to send a reply with an identifier that does not
- match an outstanding command from the peer.
- The identifier 0 is reserved.
- 6.5. Data
- The data is arbitrary data, specific to the command (and possibly state).
- Its length is defined by the length field, which may be 0.
- 7. Defined commands
- This is a comprehensive listing of all commands implemented in the version
- of Ricochet to which this document corrosponds, and potentially those used
- by other applications that are considered reserved for that purpose.
- 7.1. 0x00 - Ping
- The ping command has no data, and results in a single, final, successful
- reply with a command-specific state of 0 (0xE0). It has no other effect.
- 7.2. 0x01 - Get connection secret
- The command has no data. If successful, the peer will send a single, final
- reply with a command state of 0 (0xE0), and the 16-byte secret that is
- used to authenticate the local (command outgoing) end when establishing a
- connection.
- This is a dirty trick used during contact requests to allow the requesting
- end of the request to discover the secret that it should use.
- 7.3. 0x10 - Chat message
- The command sends the following data:
- timeDelta 32-bit signed big-endian integer; seconds
- before now that the message was written. A
- negative value (indicating the future) may be
- rejected.
- lastReceived 16-bit big-endian integer; command identifier
- of the last chat message that had been received
- from the peer when this message was sent.
- length 16-big unsigned big-endian integer; length in
- octets of the text field
- text UTF8-encoded message text of 'length' octets.
- If successful, a single, final reply will be sent.
- 8. Contact request connections
- Contact requests are indicated by a connection with a purpose of 0x80.
- Immediately after receiving the purpose, the server will respond with a
- 16-octet randomly generated cookie.
- Once the cookie is received, the client (i.e. the peer that is sending a
- request) must send the following structure:
- length 16-bit big-endian unsigned integer; length in
- octets of the entire request message, inclusive
- of itself.
- serverHostname 16 octets, base32-encoded onion hostname of the
- intended recipient of the request.
- serverCookie 16 octets, the cookie provided by the server
- connSecret 16 octets, random data that the recipient can
- use to authenticate for a contact connection.
- pubKeyLength 16-bit big-endian unsigned integer; length in
- octets of the pubKey field
- pubKey PEM-encoded hidden service public key of
- pubKeyLength octets
- nicknameLength 16-bit big-endian unsigned integer; length in
- octets of the nickname field
- nickname UTF-8 encoded string of nicknameLength octets;
- suggested nickname for this contact
- messageLength 16-bit big-endian unsigned integer; length in
- octets of the message field
- message UTF-8 encoded string of messageLength octets;
- freeform message to be shown with the request
- signatureLength 16-bit big-endian unsigned integer; length in
- octets of the signature field
- signature RSA signature of the SHA256 digest of the fields
- from serverHostname to message inclusive.
- Upon receiving the request, the server must verify that it is correct:
- - length must be greater than 58
- - serverHostname must equal the onion hostname that received this request
- - serverCookie must equal the random cookie sent by the server
- - pubKey must be a parseable and valid RSA public key
- - at least one of nickname or message must be non-empty
- - signature must be a valid signature by pubKey of the previous fields,
- excluding the length.
- Verifying serverHostname and serverCookie prevents replay and forwarding
- attacks on the request. The signature authenticates that the origin of the
- request is able to publish the hidden service represented by pubKey. The
- requesting service's hostname can be calculated from pubKey.
- After the request, the server will respond with a response code. All
- responses with the exception of 0x00 (acknowledge) and 0x01 (accept) are
- considered errors. The following are currently-defined responses:
- 0x00 Acknowledged (see below)
- 0x01 Accepted (see below)
- 0x40 Rejected by user
- 0x80 Syntax error
- 0x81 Verification error
- 0x82 Request requires either a nickname or a message
- All of the error responses (that is, any with a value greater than 0x01)
- will be followed closing the connection. In the case of user rejection,
- and potentially others, the contact ID used for this request may be added
- to a blacklist, causing any further requests to be immediately rejected
- without notifying the user.
- The acknowledged response is a special case; this indicates that the
- request was valid and has been processed, but that no response has yet been
- made. After the acknowledged response, the client should leave open the
- connection and wait for another response code to arrive. However, this is
- not a requirement.
- Immediately after the accepted response, both peers are expected to
- transition the connection to an established and authenticated command
- connection (i.e., they begin the message protocol).
- The requesting peer MUST be willing to accept normal contact connections,
- authenticated with the connSecret field from the request, at any time after
- the request has been sent. If such a connection is established, the
- requesting peer should treat that as implicitly accepting the request. This
- allows the request to be accepted if the request connection has since been
- lost.
|