{% extends "_layout.html" %} {% block title %}SSU Protocol Specification{% endblock %} {% block content %} Updated July 2010 for release 0.8
See the SSU page for an overview of the SSU transport.
The initial 2048-bit DH key exchange is described on the SSU page. This exchange uses the same shared prime as that used for I2P's ElGamal encryption.
All UDP datagrams begin with a 16 byte MAC (Message Authentication Code) and a 16 byte IV (Initialization Vector followed by a variable-size payload encrypted with the appropriate key. The MAC used is HMAC-MD5, truncated to 16 bytes, while the key is a full 32 byte AES256 key. The specific construct of the MAC is the first 16 bytes from:
HMAC-MD5(payload || IV || (payloadLength ^ protocolVersion), macKey)
The payload itself is AES256/CBC encrypted with the IV and the sessionKey, with replay prevention addressed within its body, explained below. The payloadLength in the MAC is a 2 byte unsigned integer.
The protocolVersion is a 2 byte unsigned integer and is currently set to 0. Peers using a different protocol version will not be able to communicate with this peer, though earlier versions not using this flag are.
Within the AES encrypted payload, there is a minimal common structure to the various messages - a one byte flag and a four byte sending timestamp (seconds since the unix epoch). The flag byte contains the following bitfields:
Bit order: 76543210 (bit 7 is MSB) bits 7-4: payload type bit 3: rekey? bit 2: extended options included bits 1-0: reserved
Header: 37+ bytes +----+----+----+----+----+----+----+----+ | MAC | + + | | +----+----+----+----+----+----+----+----+ | IV | + + | | +----+----+----+----+----+----+----+----+ |flag| time | (optionally | +----+----+----+----+----+ | | this may have 64 byte keying material | | and/or a one+N byte extended options) | +---------------------------------------|
If the rekey flag is set, 64 bytes of keying material follow the timestamp.
When rekeying, the first 32 bytes of the keying material is fed into a SHA256 to produce the new MAC key, and the next 32 bytes are fed into a SHA256 to produce the new session key, though the keys are not immediately used. The other side should also reply with the rekey flag set and that same keying material. Once both sides have sent and received those values, the new keys should be used and the previous keys discarded. It may be useful to keep the old keys around briefly, to address packet loss and reordering.
NOTE: Rekeying is currently unimplemented.
If the extended options flag is set, a one byte option size value is appended, followed by that many extended option bytes.
NOTE: Extended options is currently unimplemented.
All messages contain 0 or more bytes of padding. Each message must be padded to a 16 byte boundary, as required by the AES256 encryption layer. Currently, messages are not padded beyond the next 16 byte boundary. The fixed-size tunnel messages of 1024 bytes (at a higher layer) provide a significant amount of protection. In the future, additional padding in the transport layer up to a set of fixed packet sizes may be appropriate to further hide the data fragmentation to external adversaries.
Both introduction keys and session keys are 32 bytes, and are defined by the Common structures specification. The key used for the MAC and encryption is specified for each message below.
There are 10 messages (payload types) defined:
Type | Message | Notes |
---|---|---|
0 | SessionRequest | |
1 | SessionCreated | |
2 | SessionConfirmed | |
3 | RelayRequest | |
4 | RelayResponse | |
5 | RelayIntro | |
6 | Data | |
7 | PeerTest | |
8 | SessionDestroyed | Unimplemented |
n/a | HolePunch |
This is the first message sent to establish a session.
Peer: | Alice to Bob |
Data: |
|
Key used: | introKey |
+----+----+----+----+----+----+----+----+ | X, as calculated from DH | | | . . . | | +----+----+----+----+----+----+----+----+ |size| that many byte IP address (4-16) | +----+----+----+----+----+----+----+----+ | arbitrary amount | | of uninterpreted data | . . . | | +----+----+----+----+----+----+----+----+
Typical size including header, in current implementation: 304 bytes
This is the response to a Session Request.
Peer: | Bob to Alice |
Data: |
|
Key used: | introKey, with an additional layer of encryption over the 40 byte signature and the following 8 bytes padding. |
+----+----+----+----+----+----+----+----+ | Y, as calculated from DH | | | . . . | | +----+----+----+----+----+----+----+----+ |size| that many byte IP address (4-16) | +----+----+----+----+----+----+----+----+ | Port (A)| public relay tag | signed +----+----+----+----+----+----+----+----+ on time | | +----+----+ | | DSA signature | + + | | + + | | + + | | + +----+----+----+----+----+----+ | | (8 bytes of padding) +----+----+----+----+----+----+----+----+ | | +----+----+ | | arbitrary amount | | of uninterpreted data | . . . | | +----+----+----+----+----+----+----+----+
Typical size including header, in current implementation: 368 bytes
This is the response to a Session Created message and the last step in establishing a session. There may be multiple Session Confirmed messages required if the Router Identity must be fragmented.
Peer: | Alice to Bob |
Data: |
|
Key used: | sessionKey |
Fragment 0 through F-2 +----+----+----+----+----+----+----+----+ |info| cursize | | +----+----+----+ | | fragment of Alice's full | | Router Identity | . . . | | +----+----+----+----+----+----+----+----+ | arbitrary amount of uninterpreted | | data | +----+----+----+----+----+----+----+----+ Fragment F-1: +----+----+----+----+----+----+----+----+ |info| cursize | | +----+----+----+ | | last fragment of Alice's full | | Router Identity | . . . | | +----+----+----+----+----+----+----+----+ | signed on time | | +----+----+----+----+ | | arbitrary amount of uninterpreted | | data, to 40 bytes prior to | | end of the current packet | +----+----+----+----+----+----+----+----+ | DSA signature | + + | | + + | | + + | | + + | | +----+----+----+----+----+----+----+----+
Typical size including header, in current implementation: 480 bytes
Currently unimplemented, scheduled for implementation in version 0.8.1. Subject to change.
Peer: | Alice to Bob or Bob to Alice |
Data: | none |
Key used: | sessionKey or introKey |
+----+----+----+----+----+----+----+----+ | no data | +----+----+----+----+----+----+----+----+
This is the first message sent from Alice to Bob to request an introduction to Charlie.
Peer: | Alice to Bob |
Data: |
|
Key used: | introKey (or sessionKey, if Alice/Bob is established) |
+----+----+----+----+----+----+----+----+ | relay tag |size| Alice IP addr +----+----+----+----+----+--- +----+----| | Port (A)|size| challenge bytes | +----+----+----+----+ + | to be delivered to Charlie | +----+----+----+----+----+----+----+----+ | Alice's intro key | + + | | + + | | + + | | +----+----+----+----+----+----+----+----+ | nonce | | +----+----+----+----+ | | arbitrary amount of uninterpreted data| +----+----+----+----+----+----+----+----+
Typical size including header, in current implementation: 96 bytes
This is the response to a Relay Request and is sent from Bob to Alice.
Peer: | Bob to Alice |
Data: |
|
Key used: | introKey (or sessionKey, if Alice/Bob is established) |
+----+----+----+----+----+----+----+----+ |size| Charlie IP | Port (C)|size| +----+----+----+----+----+----+----+----+ | Alice IP | Port (A)| nonce +----+----+----+----+----+----+----+----+ | arbitrary amount of | +----+----+ | | uninterpreted data | +----+----+----+----+----+----+----+----+
Typical size including header, in current implementation: 64 bytes
This is the introduction for Alice, which is sent from Bob to Charlie.
Peer: | Bob to Charlie |
Data: |
|
Key used: | sessionKey |
+----+----+----+----+----+----+----+----+ |size| Alice IP | Port (A)|size| +----+----+----+----+----+----+----+----+ | that many bytes of challenge | + | | data relayed from Alice | +----+----+----+----+----+----+----+----+ | arbitrary amount of uninterpreted data| +----+----+----+----+----+----+----+----+
Typical size including header, in current implementation: 48 bytes
This message is used for data transport and acknowledgment.
Peer: | Any |
Data: |
|
Key used: | sessionKey |
+----+----+----+----+----+----+----+----+ |flag| (additional headers, determined | +----+ | | by the flags, such as ACKs or | | bitfields | +----+----+----+----+----+----+----+----+ |#frg| messageId | frag info | +----+----+----+----+----+----+----+----+ | that many bytes of fragment data | . . . | | +----+----+----+----+----+----+----+----+ | messageId | frag info | | +----+----+----+----+----+----+----+ | | that many bytes of fragment data | . . . | | +----+----+----+----+----+----+----+----+ | messageId | frag info | | +----+----+----+----+----+----+----+ | | that many bytes of fragment data | . . . | | +----+----+----+----+----+----+----+----+ | arbitrary amount of uninterpreted data| +----+----+----+----+----+----+----+----+
See the UDP overview page for details.
Peer: | Any |
Data: |
|
Key used: | introKey (or sessionKey if the connection has already been established) |
+----+----+----+----+----+----+----+----+ | test nonce |size| Alice IP addr +----+----+----+----+----+----+----+----+ | Port (A)| | +----+----+----+ + | Alice or Charlie's | + introduction key (Alice's is sent to + | Bob and Charlie, while Charlie's is | + sent to Alice) + | | | +----+----+----+----+----+ | | arbitrary amount of | |----+----+----+ | | uninterpreted data | +----+----+----+----+----+----+----+----+
Typical size including header, in current implementation: 80 bytes
A HolePunch is simply a UDP packet with no data. It is unauthenticated and unencrypted. It does not contain a SSU header, so it does not have a message type number. It is sent from Charlie to Alice as a part of the Introduction sequence.
+----+----+----+----+----+----+----+----+ | MAC | + + | | +----+----+----+----+----+----+----+----+ | IV | + + | | +----+----+----+----+----+----+----+----+ |flag| time |flag|#frg| | +----+----+----+----+----+----+----+ | | padding to fit a full AES256 block | +----+----+----+----+----+----+----+----+Minimal data message with payload
+----+----+----+----+----+----+----+----+ | MAC | + + | | +----+----+----+----+----+----+----+----+ | IV | + + | | +----+----+----+----+----+----+----+----+ |flag| time |flag|#frg| +----+----+----+----+----+----+----+----+ messageId | frag info | | +----+----+----+----+----+----+ | | that many bytes of fragment data | . . . | | +----+----+----+----+----+----+----+----+{% endblock %}