From d9b5bbd079413f0eaa18b3590d2bd015540747e0 Mon Sep 17 00:00:00 2001
From: zzz <zzz@i2pmail.org>
Date: Sat, 2 Apr 2022 07:43:18 -0400
Subject: [PATCH] Prop. 159: More on Sess. Conf. fragmentation

---
 i2p2www/spec/proposals/159-ssu2.rst | 61 +++++++++++++++++++++++++----
 1 file changed, 54 insertions(+), 7 deletions(-)

diff --git a/i2p2www/spec/proposals/159-ssu2.rst b/i2p2www/spec/proposals/159-ssu2.rst
index a84418a79..77dfea9e6 100644
--- a/i2p2www/spec/proposals/159-ssu2.rst
+++ b/i2p2www/spec/proposals/159-ssu2.rst
@@ -5,7 +5,7 @@ SSU2
     :author: eyedeekay, orignal, zlatinb, zzz
     :created: 2021-09-12
     :thread: http://zzz.i2p/topics/2612
-    :lastupdated: 2022-04-01
+    :lastupdated: 2022-04-02
     :status: Open
     :target: 0.9.56
 
@@ -2776,7 +2776,7 @@ Once a session has been established, Alice and Bob can exchange Data messages.
 Packet Header
 ---------------
 
-All packets start with an obfuscated header.
+All packets start with an obfuscated (encrypted) header.
 There are two header types, long and short.
 
 Long Header
@@ -2784,7 +2784,7 @@ Long Header
 The long header is 32 bytes. It is used before a session is created, for SessionRequest, SessionCreated, and Retry.
 Note that the first 9 bytes (Destination Connection ID and type) are the same for both headers.
 
-Before header obfuscation and protection:
+Before header encryption:
 
 .. raw:: html
 
@@ -2821,15 +2821,44 @@ Before header obfuscation and protection:
 
 Short Header
 `````````````
-The short header is 16 bytes. It is used after a session is created, for Data messages.
-or (maybe?) for unauthenticated messages.
+The short header is 16 bytes. It is used for Session Created and for Data messages.
+Uauthenticated messages such as Session Request, Retry, and Peer Test will
+always use the long header.
 
 16 bytes is required, because
 the receiver must decrypt the first 16 bytes to get the message type,
 and then must decrypt an additional 16 bytes if it's actually a long header,
 as indicated by the message type.
 
-Before header obfuscation and protection:
+For Session Confirmed, before header encryption:
+
+.. raw:: html
+
+  {% highlight lang='dataspec' %}
+
++----+----+----+----+----+----+----+----+
+  |      Destination Connection ID        |
+  +----+----+----+----+----+----+----+----+
+  |   Packet Number   |type|frag|  flags  |
+  +----+----+----+----+----+----+----+----+
+
+  Destination Connection ID :: 8 bytes, unsigned big endian integer
+
+  Packet Number :: 4 bytes, all zeros
+
+  type :: The message type = 2
+
+  frag :: 1 byte fragment info:
+         bit order: 76543210 (bit 7 is MSB)
+         bits 7-4: fragment number 0-14, big endian
+         bits 3-0: total fragments 1-15, big endian
+
+  flags :: 2 bytes, unused, set to 0 for future compatibility
+
+{% endhighlight %}
+
+
+For Data messages, before header encryption:
 
 .. raw:: html
 
@@ -4239,11 +4268,20 @@ Construct the series of packets as follows:
   k_header_1 and k_header_2 as defined above in the Session Confirmed KDF.
 - Transmit all fragments
 
-When Bob receives any fragment (possibly out-of order), he decrypts the header,
+Reassembly process:
+
+When Bob receives any Session Confirmed message, he decrypts the header,
 inspects the frag field, and determines that the Session Confirmed is fragmented.
 He does not (and cannot) decrypt the message until all fragments are received
 and reassembled.
 
+- Preserve the header for fragment 0, as it is used as the Noise AD
+- Discard the headers for other fragments before reassembly
+- Reassemble the "jumbo" payload, with the header for fragment 0 as AD,
+  and decrypt with Noise
+- Validate the RI block as usual
+- Proceed to the data phase and send ACK 0, as usual
+
 There is no mechanism for Bob to ack individual fragments. When Bob receives all
 fragments, reassembles, decrypts, and validates the contents, Bob does a split()
 as usual, enters the data phase, and sends an ACK of packet number 0.
@@ -4252,6 +4290,7 @@ If Alice does not receive an ACK of packet number 0, she must retransmit all
 session confirmed packets as-is.
 
 Examples:
+
 For 1500 MTU over IPv6, max payload is 1372, RI block overhead is 5,
 max (gzip compressed) RI data size is 1367 (assuming no other blocks).
 With two packets, the overhead of the 2nd packet is 64, so it can hold
@@ -4262,6 +4301,14 @@ The largest compressed RI seen in the current network is about 1400 bytes;
 therefore, in practice, two fragments should be enough, even with
 a minimum 1280 MTU. The protocol allows for 15 fragments max.
 
+Security analysis:
+
+The integrity and security of a fragmented Session Confirmed is the same as that
+of an unfragmented one. Any alteration of any fragment will cause the
+Noise AEAD to fail after reassembly. The headers of the fragments after fragment
+0 are only used to identify the fragment. Even if an on-path attacker had the
+k_header_2 key used to encrypt the header (unlikely, derived from the handshake),
+this would not allow the attacker to substitute a valid fragment.
 
 
 
-- 
GitLab