Files
i2p.www/www.i2p2/pages/udp_spec.html

538 lines
21 KiB
HTML
Raw Normal View History

2010-07-28 01:13:15 +00:00
{% extends "_layout.html" %}
{% block title %}SSU Specification{% endblock %}
{% block content %}
Updated July 2010 for release 0.8
<p>
<a href="udp.html">See the SSU page for an overview of the SSU transport</a>.
<h1>Specification</h1>
<p>
The goal of this protocol is to provide secure, authenticated,
semireliable, and unordered message delivery, exposing only a minimal
amount of data easily discernible to third parties. It should
support high degree communication as well as TCP-friendly congestion
control, and may include PMTU detection. It should be capable of
efficiently moving bulk data at rates sufficient for home users.
In addition, it should support techniques for addressing network
obstacles, like most NATs or firewalls.</p>
2010-07-28 06:10:34 +00:00
<h2 id="addressing">Addressing and introduction</h2>
2010-07-28 01:13:15 +00:00
<p>To contact an SSU peer, one of two sets of information is necessary:
a direct address, for when the peer is publicly reachable, or an
indirect address, for using a third party to introduce the peer.
There is no restriction on the number of addresses a peer may have.</p>
<pre>
Direct: ssu://host:port/introKey[?opts=[A-Z]*]
Indirect: ssu://tag@relayhost:port/relayIntroKey/targetIntroKey[?opts=[A-Z]*]
</pre>
<p>These introduction keys are delivered through an external channel
(the network database, where they are identical to the router Hash for now)
and must be used when establishing a session key. For the indirect
address, the peer must first contact the relayhost and ask them for
an introduction to the peer known at that relayhost under the given
tag. If possible, the relayhost sends a message to the addressed
peer telling them to contact the requesting peer, and also gives
the requesting peer the IP and port on which the addressed peer is
located. In addition, the peer establishing the connection must
already know the public keys of the peer they are connecting to (but
not necessary to any intermediary relay peer).</p>
<p>Each of the addresses may also expose a series of options - special
capabilities of that particular peer. For a list of available
capabilities, see <a href="#capabilities">below</a>.</p>
2010-07-28 06:10:34 +00:00
<h2 id="header">Header</h2>
2010-07-28 01:13:15 +00:00
<p>
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:</p>
<pre>
HMAC-MD5(payload || IV || (payloadLength ^ protocolVersion), macKey)
</pre>
<p>The protocol version is currently 0.</p>
<p>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 in 2s complement.</p>
<p>The protocolVersion is a 2 byte unsigned integer in 2s complement,
and 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.</p>
2010-07-28 06:10:34 +00:00
<h2 id="payload">Payload</h2>
2010-07-28 01:13:15 +00:00
<p>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:</p>
<pre>
bits 0-3: payload type
bit 4: rekey?
bit 5: extended options included
bits 6-7: reserved
</pre>
<p>If the rekey flag is set, 64 bytes of keying material follow the
timestamp. If the extended options flag is set, a one byte option
size value is appended to, followed by that many extended option
bytes, which are currently uninterpreted.</p>
<p>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.</p>
<p>NOTE: Rekeying is currently unimplemented.</p>
<pre>
Header: 37+ bytes
+----+----+----+----+----+----+----+----+
| MAC |
| |
+----+----+----+----+----+----+----+----+
| IV |
| |
+----+----+----+----+----+----+----+----+
|flag| time | (optionally |
+----+----+----+----+----+ |
| this may have 64 byte keying material |
| and/or a one+N byte extended options) |
+---------------------------------------|
</pre>
2010-07-28 06:10:34 +00:00
<h2 id="messages">Messages</h2>
2010-07-28 01:13:15 +00:00
<p>
There are 8 messages defined:
</p><p>
<table border="1">
<tr><th>Type<th>Message<th>Notes
<tr><td align="center">0<td>SessionRequest
<tr><td align="center">1<td>SessionCreated
<tr><td align="center">2<td>SessionConfirmed
<tr><td align="center">8<td>SessionDestroyed<td>Unimplemented
<tr><td align="center">3<td>RelayRequest
<tr><td align="center">4<td>RelayResponse
<tr><td align="center">5<td>RelayIntro
<tr><td align="center">6<td>Data
<tr><td align="center">7<td>PeerTest
</table>
</p>
2010-07-28 06:10:34 +00:00
<h3 id="sessionRequest">SessionRequest (type 0)</h3>
2010-07-28 01:13:15 +00:00
<table border="1">
<tr><td align="right" valign="top"><b>Peer:</b></td>
<td>Alice to Bob</td></tr>
<tr><td align="right" valign="top"><b>Data:</b></td>
<td><ul>
<li>256 byte X, to begin the DH agreement</li>
<li>1 byte IP address size</li>
<li>that many byte representation of Bob's IP address</li>
<li>N bytes, currently uninterpreted (later, for challenges)</li>
</ul></td></tr>
<tr><td align="right" valign="top"><b>Key used:</b></td>
<td>introKey</td></tr>
</table>
<pre>
+----+----+----+----+----+----+----+----+
| X, as calculated from DH |
| |
. . .
| |
+----+----+----+----+----+----+----+----+
|size| that many byte IP address (4-16) |
+----+----+----+----+----+----+----+----+
| arbitrary amount |
| of uninterpreted data |
. . .
| |
+----+----+----+----+----+----+----+----+
</pre>
2010-07-28 06:10:34 +00:00
<h3 id="sessionCreated">SessionCreated (type 1)</h3>
2010-07-28 01:13:15 +00:00
<table border="1">
<tr><td align="right" valign="top"><b>Peer:</b></td>
<td>Bob to Alice</td></tr>
<tr><td align="right" valign="top"><b>Data:</b></td>
<td><ul>
<li>256 byte Y, to complete the DH agreement</li>
<li>1 byte IP address size</li>
<li>that many byte representation of Alice's IP address</li>
<li>2 byte port number (unsigned, big endian 2s complement)</li>
<li>4 byte relay tag which Alice can publish (else 0x0)</li>
<li>4 byte timestamp (seconds from the epoch) for use in the DSA
signature</li>
<li>40 byte DSA signature of the critical exchanged data
(X + Y + Alice's IP + Alice's port + Bob's IP + Bob's port + Alice's
new relay tag + Bob's signed on time), encrypted with another
layer of encryption using the negotiated sessionKey. The IV
is reused here.</li>
<li>8 bytes padding, encrypted with an additional layer of encryption
using the negotiated session key as part of the DSA block</li>
<li>N bytes, currently uninterpreted (later, for challenges)</li>
</ul></td></tr>
<tr><td align="right" valign="top"><b>Key used:</b></td>
<td>introKey, with an additional layer of encryption over the 40 byte
signature and the following 8 bytes padding.</td></tr>
</table>
<pre>
+----+----+----+----+----+----+----+----+
| 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 |
. . .
| |
+----+----+----+----+----+----+----+----+
</pre>
2010-07-28 06:10:34 +00:00
<h3 id="sessionConfirmed">SessionConfirmed (type 2)</h3>
2010-07-28 01:13:15 +00:00
<table border="1">
<tr><td align="right" valign="top"><b>Peer:</b></td>
<td>Alice to Bob</td></tr>
<tr><td align="right" valign="top"><b>Data:</b></td>
<td><ul>
<li>1 byte identity fragment info:<pre>
bits 0-3: current identity fragment #
bits 4-7: total identity fragments</pre></li>
<li>2 byte size of the current identity fragment</li>
<li>that many byte fragment of Alice's identity.</li>
<li>on the last identity fragment, the signed on time is
included after the identity fragment, and the last 40
bytes contain the DSA signature of the critical exchanged
data (X + Y + Alice's IP + Alice's port + Bob's IP + Bob's port
+ Alice's new relay key + Alice's signed on time)</li>
</ul></td></tr>
<tr><td align="right" valign="top"><b>Key used:</b></td>
<td>sessionKey</td></tr>
</table>
<pre>
<b>Fragment 1 through N-1</b>
+----+----+----+----+----+----+----+----+
|info| cursize | |
+----+----+----+ |
| fragment of Alice's full |
| identity keys |
. . .
| |
+----+----+----+----+----+----+----+----+
<b>Fragment N:</b>
+----+----+----+----+----+----+----+----+
|info| cursize | |
+----+----+----+ |
| fragment of Alice's full |
| identity keys |
. . .
| |
+----+----+----+----+----+----+----+----+
| signed on time | |
+----+----+----+----+ |
| arbitrary amount of uninterpreted |
| data, up from the end of the |
| identity key to 40 bytes prior to |
| end of the current packet |
+----+----+----+----+----+----+----+----+
| DSA signature |
| |
| |
| |
| |
+----+----+----+----+----+----+----+----+
</pre>
2010-07-28 06:10:34 +00:00
<h3 id="sessionDestroyed">SessionDestroyed (type 8)</h3>
2010-07-28 01:13:15 +00:00
Currently unimplemented, scheduled for implementation in version 0.8.1.
<table border="1">
<tr><td align="right" valign="top"><b>Peer:</b></td>
<td>Alice to Bob or Bob to Alice</td></tr>
<tr><td align="right" valign="top"><b>Data:</b></td>
<td>none
</td></tr>
<tr><td align="right" valign="top"><b>Key used:</b></td>
<td>sessionKey or introKey</td></tr>
</table>
<pre>
+----+----+----+----+----+----+----+----+
| no data |
+----+----+----+----+----+----+----+----+
</pre>
2010-07-28 06:10:34 +00:00
<h3 id="relayRequest">RelayRequest (type 3)</h3>
2010-07-28 01:13:15 +00:00
<table border="1">
<tr><td align="right" valign="top"><b>Peer:</b></td>
<td>Alice to Bob</td></tr>
<tr><td align="right" valign="top"><b>Data:</b></td>
<td><ul>
<li>4 byte relay tag</li>
<li>1 byte IP address size</li>
<li>that many byte representation of Alice's IP address</li>
<li>2 byte port number (of Alice)</li>
<li>1 byte challenge size</li>
<li>that many bytes to be relayed to Charlie in the intro</li>
<li>Alice's intro key (so Bob can reply with Charlie's info)</li>
<li>4 byte nonce of alice's relay request</li>
<li>N bytes, currently uninterpreted</li>
</ul></td></tr>
<tr><td align="right" valign="top"><b>Key used:</b></td>
<td>introKey (or sessionKey, if Alice/Bob is established)</td></tr>
</table>
<pre>
+----+----+----+----+----+----+----+----+
| relay tag |size| that many |
+----+----+----+----+----+ +----|
| bytes for Alice's IP address |port
+----+----+----+----+----+----+----+----+
(A) |size| that many challenge bytes |
+----+----+ |
| to be delivered to Charlie |
+----+----+----+----+----+----+----+----+
| Alice's intro key |
| |
| |
| |
+----+----+----+----+----+----+----+----+
| nonce | |
+----+----+----+----+ |
| arbitrary amount of uninterpreted data|
+----+----+----+----+----+----+----+----+
</pre>
2010-07-28 06:10:34 +00:00
<h3 id="relayResponse">RelayResponse (type 4)</h3>
2010-07-28 01:13:15 +00:00
<table border="1">
<tr><td align="right" valign="top"><b>Peer:</b></td>
<td>Bob to Alice</td></tr>
<tr><td align="right" valign="top"><b>Data:</b></td>
<td><ul>
<li>1 byte IP address size</li>
<li>that many byte representation of Charlie's IP address</li>
<li>2 byte port number</li>
<li>1 byte IP address size</li>
<li>that many byte representation of Alice's IP address</li>
<li>2 byte port number</li>
<li>4 byte nonce sent by Alice</li>
<li>N bytes, currently uninterpreted</li>
</ul></td></tr>
<tr><td align="right" valign="top"><b>Key used:</b></td>
<td>introKey (or sessionKey, if Alice/Bob is established)</td></tr>
</table>
<pre>
+----+----+----+----+----+----+----+----+
|size| that many bytes making up |
+----+ +----+----+
| Charlie's IP address | Port (C)|
+----+----+----+----+----+----+----+----+
|size| that many bytes making up |
+----+ +----+----+
| Alice's IP address | Port (A)|
+----+----+----+----+----+----+----+----+
| nonce | |
+----+----+----+----+ |
| arbitrary amount of uninterpreted data|
+----+----+----+----+----+----+----+----+
</pre>
2010-07-28 06:10:34 +00:00
<h3 id="relayIntro">RelayIntro (type 5)</h3>
2010-07-28 01:13:15 +00:00
<table border="1">
<tr><td align="right" valign="top"><b>Peer:</b></td>
<td>Bob to Charlie</td></tr>
<tr><td align="right" valign="top"><b>Data:</b></td>
<td><ul>
<li>1 byte IP address size</li>
<li>that many byte representation of Alice's IP address</li>
<li>2 byte port number (of Alice)</li>
<li>1 byte challenge size</li>
<li>that many bytes relayed from Alice</li>
<li>N bytes, currently uninterpreted</li>
</ul></td></tr>
<tr><td align="right" valign="top"><b>Key used:</b></td>
<td>sessionKey</td></tr>
</table>
<pre>
+----+----+----+----+----+----+----+----+
|size| that many bytes making up |
+----+ +----+----+
| Alice's IP address | Port (A)|
+----+----+----+----+----+----+----+----+
|size| that many bytes of challenge |
+----+ |
| data relayed from Alice |
+----+----+----+----+----+----+----+----+
| arbitrary amount of uninterpreted data|
+----+----+----+----+----+----+----+----+
</pre>
2010-07-28 06:10:34 +00:00
<h3 id="data">Data (type 6)</h3>
2010-07-28 01:13:15 +00:00
<table border="1">
<tr><td align="right" valign="top"><b>Peer:</b></td>
<td>Any</td></tr>
<tr><td align="right" valign="top"><b>Data:</b></td>
<td><ul>
<li>1 byte flags:<pre>
bit 0: explicit ACKs included
bit 1: ACK bitfields included
bit 2: reserved
bit 3: explicit congestion notification
bit 4: request previous ACKs
bit 5: want reply
bit 6: extended data included
bit 7: reserved</pre></li>
<li>if explicit ACKs are included:<ul>
<li>a 1 byte number of ACKs</li>
<li>that many 4 byte MessageIds being fully ACKed</li>
</ul></li>
<li>if ACK bitfields are included:<ul>
<li>a 1 byte number of ACK bitfields</li>
<li>that many 4 byte MessageIds + a 1 or more byte ACK bitfield.
The bitfield uses the 7 low bits of each byte, with the high
bit specifying whether an additional bitfield byte follows it
(1 = true, 0 = the current bitfield byte is the last). These
sequence of 7 bit arrays represent whether a fragment has been
received - if a bit is 1, the fragment has been received. To
clarify, assuming fragments 0, 2, 5, and 9 have been received,
the bitfield bytes would be as follows:<pre>
byte 0
bit 0: 1 (further bitfield bytes follow)
bit 1: 1 (fragment 0 received)
bit 2: 0 (fragment 1 not received)
bit 3: 1 (fragment 2 received)
bit 4: 0 (fragment 3 not received)
bit 5: 0 (fragment 4 not received)
bit 6: 1 (fragment 5 received)
bit 7: 0 (fragment 6 not received)
byte 1
bit 0: 0 (no further bitfield bytes)
bit 1: 0 (fragment 7 not received)
bit 1: 0 (fragment 8 not received)
bit 1: 1 (fragment 9 received)
bit 1: 0 (fragment 10 not received)
bit 1: 0 (fragment 11 not received)
bit 1: 0 (fragment 12 not received)
bit 1: 0 (fragment 13 not received)</pre></li>
</ul></li>
<li>If extended data included:<ul>
<li>1 byte data size</li>
<li>that many bytes of extended data (currently uninterpreted)</li></ul></li>
<li>1 byte number of fragments (can be zero)</li>
<li>If nonzero, that many message fragments:<ul>
<li>4 byte messageId</li>
<li>3 byte fragment info:<pre>
bits 0-6: fragment #
bit 7: isLast (1 = true)
bits 8-9: unused
bits 10-23: fragment size</pre></li>
<li>that many bytes</li></ul>
<li>N bytes padding, uninterpreted</li>
</ul></td></tr>
<tr><td align="right" valign="top"><b>Key used:</b></td>
<td>sessionKey</td></tr>
</table>
<pre>
+----+----+----+----+----+----+----+----+
|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|
+----+----+----+----+----+----+----+----+
</pre>
2010-07-28 06:10:34 +00:00
<h3 id="peerTest">PeerTest (type 7)</h3>
2010-07-28 01:13:15 +00:00
<table border="1">
<tr><td align="right" valign="top"><b>Peer:</b></td>
<td><a href="#peerTesting">Any</a></td></tr>
<tr><td align="right" valign="top"><b>Data:</b></td>
<td><ul>
<li>4 byte nonce</li>
<li>1 byte IP address size</li>
<li>that many byte representation of Alice's IP address</li>
<li>2 byte port number</li>
<li>Alice's introduction key</li>
<li>N bytes, currently uninterpreted</li>
</ul></td></tr>
<tr><td align="right" valign="top"><b>Key used:</b></td>
<td>introKey (or sessionKey if the connection has already been established)</td></tr>
</table>
<pre>
+----+----+----+----+----+----+----+----+
| test nonce |size| that many |
+----+----+----+----+----+ |
|bytes making up Alice's IP address |
|----+----+----+----+----+----+----+----+
| 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 |
+----+----+----+----+----+----+----+----+
</pre>
{% endblock %}