1# Cryptography in n2n
2
3## Payload
4
5### Overview
6
7Payload encryption currently comes in four different flavors using ciphers of different origins. Supported ciphers are enabled using the indicated command line option:
8
9- Twofish in CTS mode (`-A2`)
10- AES in CBC mode (`-A3`)
11- ChaCha20 (CTR) (`-A4`)
12- SPECK in CTR mode (`-A5`)
13
14To renounce encryption, `-A1` enables the so called `null_transform` transmitting all payload data unencryptedly.
15
16The following chart might help to make a quick comparison and decide what cipher to use:
17
18| Cipher | Mode | Block Size | Key Size         | IV length |Speed | Built-In | Origin |
19| :---:  | :---:| :---:      | :---:            | :---:     |:---: | :---:    | ---    |
20|Twofish | CTS  | 128 bits   | 256 bit          | 32 bit    | -    | Y        | Bruce Schneier |
21|AES     | CBC  | 128 bits   | 128, 192, 256 bit| 64 bit    | O..+ | N        | Joan Daemen, Vincent Rijmen, NSA-approved |
22|ChaCha20| CTR  | Stream     | 256 bit          | 128 bit   | +..++| N        | Daniel J. Bernstein |
23|SPECK   | CTR  | Stream     | 256 bit          | 128 bit   | ++   | Y        | NSA |
24
25The two block ciphers Twofish and AES are used in CTS mode (Twofish) and CBC mode(AES). AES requires a padding which results in encrypted payload size modulo their blocksize. Sizewise, this could be considered as a disadvantage. On the other hand, stream ciphers need a longer initialization vector (IV) to be transmitted with the cipher.
26
27Note that AES and ChaCha20 are available only if n2n is compiled with openSSL support. n2n will work well without them offering the respectively reduced choice of remaining built-in ciphers (Twofish, SPECK).
28
29### Twofish
30
31This implementation prepends a 32 bit random value to the plain text. In the `src/transform_tf.c` file, it is called `nonce`. In CBC mode, this basically has the same effect as a respectively shorter IV.
32
33Twofish requires no padding as it employs a CBC/CTS scheme which can send out plaintext-length ciphertexts. The scheme however has a small flaw in handling messages shorter than one block, only low-level programmer might encounter this.
34
35Twofish is the slowest of the ciphers present.
36
37_We might try to find a faster implementation._
38
39### AES
40
41AES uses the standard way of an IV but it does not neccessarily transmit the full IV along with the packets. The size of the transmitted part is adjustable by changing the `TRANSOP_AES_IV_SEED_SIZE` definition found in `src/transform_aes.c`. It defaults to 8 meaning that 8 bytes (of max 16) are transmitted. The remaining 8 bytes are fixed, key-derived material is used to fill up to full block size. A single AES-ECB encryption step is applied to these 16 bytes before they get used as regular IV for AES-CBCing the payload.
42
43Padding to the last block happens by filling `0x00`-bytes and indicating their number as the last byte of the block. This could lead to up to 16 extra bytes.
44
45AES relies on openSSL's `evp_*` interface which also offers hardware acceleration where available (SSE, AES-NI, …). It however is slower than the following stream ciphers because the CBC mode cannot compete with the optimized stream ciphers.
46
47_Perhaps, AES-CTR being a stream cipher could have competed with the stream ciphers._
48
49_Another possible extension would be to bring CTS mode to AES in some future version, just to avoid unneccessary weight gains from padding. CTS mode works well starting with plain texts from one block plus. So, we might revert back to the Twofish-way of IV handling with a full block IV._
50
51### ChaCha20
52
53ChaCha20 was the first stream cipher supported by n2n.
54
55It also relies on openSSL's `evp_*` interface. It does not use the Poly1305 message tag from the same author though. Whole packet's checksum will be handled in the header (see below).
56
57The random full 128-bit IV is transmitted in plain.
58
59ChaCha20 usually performs faster than AES-CBC.
60
61### SPECK
62
63SPECK is recommended by the NSA for offical use in case AES implementation is not feasible due to system constraints (performance, size, …). The block cipher is used in CTR mode making it a stream cipher. The random full 128-bit IV is transmitted in plain.
64
65On Intel CPUs, SPECK performs even faster than openSSL's ChaCha20 as it takes advantage of SSE4 or AVX2 if available (compile using `-march=native`). On Raspberry's ARM CPU, it is second place behind ChaCha20 and before AES-CBC.
66
67### Random Numbers
68
69Throughout n2n, pseudo-random numbers are generated for several purposes, e.g. random MAC assignment and the IVs for use with the various ciphers. Regarding IVs, especially for using in the stream ciphers, the pseudo-random numbers shall be as collision-free as possible. n2n uses an implementation of XORSHIFT128+ which shows a periodicity of 2¹²⁸.
70
71Its initialization relies on seeding with a value as random as possible. Various sources are tapped including a syscall to Linux' `SYS_getrandom` as well as Intels hardware random number generators `RDRND` and `RDSEED`, if available (compile using `-march=native`).
72
73### Pearson Hashing
74
75For general purpose hashing, n2n employs Pearson hashing as it offers variable hash sizes and is said not to be too "collidy". However, this is not a cryptographically secure hashing function which by the way is not required here: The hashing is never applied in a way that the hash shall prove the knowledge of a secret without showing the secret.
76
77_Pearson hashing is tweakable by making your own permutation of the 256 byte table._
78
79_Pearson hashing allows verification of parts of the hash only – just in case performance requirements would urge to do so._
80
81## Header
82
83### Overview
84
85Packet's header consist of a COMMON section followed by a packet-type specific section, e.g. REGISTER, REGISTER_ACK, PACKET including the payload, REGISTER_SUPER, …
86
87The COMMON section is built as follows:
88
89```
900 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
91   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
92   ! Version=2     ! TTL           ! Flags                         !
93   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
94 4 ! Community                                                     :
95   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
96 8 ! ... Community ...                                             :
97   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
9812 ! ... Community ...                                             :
99   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
10016 ! ... Community ...                                             !
101   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
102```
103
104In case of a PACKET-type, it is succeeded by the fields depicted below:
105
106```
107    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
108   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
10920 ! Source MAC Address                                            :
110   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
11124 :                               ! Destination MAC Address       :
112   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
11328 :                                                               !
114   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
11532 ! Socket Flags (v=IPv4)         ! Destination UDP Port          !
116   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
11736 ! Destination IPv4 Address                                      !
118   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
11940 ! Transform ID                  ! Payload ...                   !
120   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
12144 !
122   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+...
123```
124### Encryption
125
126If enabled (`-H`), all fields but the payload (which is handled seperately as outlined above) get encrypted using SPECK in CTR mode. As packet headers need to be decryptable by the supernode and we do not want to add another key (to keep it a simple interface), the community name serves as key (keep it secret!) because it is already known to the supernode. The community name consists of up to 16 characters (well, 15 + `0x00`), so key size of 128 bit is a reasonable choice here.
127
128The scheme applied tries to maintain compatibility with current packet format and works as follows:
129
130- First line of 4 bytes (Version, TTL, Flags) goes to fifth line:
131```
132    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
133   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
134   ! Community ...                                                 :
135   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
136 4 ! ... Community ...                                             :
137   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
138 8 ! ... Community ...                                             :
139   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
14012 ! ... Community                                                 !
141   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
14216 ! Version=2     ! TTL           ! Flags                         !
143   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
144```
145- To be able to identify a correctly decrpyted header later on, a magic number is stamped in fourth line starting at byte number 12. We use "n2n" string and add the header length to be able to stop header decryption right before an eventually following payload begins – in case of PACKET-type, header-length does not equal packet-length.
146
147- The rest of the community field, namely the first 12 bytes, is reframed towards a 96-bit IV for the header encryption.
148```
149    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
150   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
151   ! IV ...                                                        :
152   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
153 4 ! ... IV ...                                                    :
154   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
155 8 ! ... IV                                                        :
156   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15712 ! 24-bit Magic Number, "n2n" = 0x6E326E         ! Header Length !
158   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15916 ! Version=2     ! TTL           ! Flags                         !
160   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
161```
162
163- As we use a stream cipher, the IV should be a nonce. The IV plays an additional role sketched later, see the following sections on checksum and replay protection. For use in header encryption and decryption, four bytes reading ASCII "n2n!" are appended to the 96-bit IV hereby internally making it a full 128-bit IV.
164
165- To make a less predictable use of the key space – just think of the typically reset MSB of ASCII characters of community names – we actually use a hash of the community name as key.
166
167- Encryption starts at byte number 12 and ends at header's end. It does not comprise the payload which eventually has its own encryption scheme as chosen with the `-A_` options.
168
169Decryption checks all known communities (several in case of supernode, only one at edge) as keys. On success, the emerging magic number will reveal the correct community whose name will be copied back to the original fields allowing for regular packet handling.
170
171Thus, header encryption will only work with previously determined community names introduced to the supernode by `-c <path>` parameter. Also, it should be clear that header encryption is a per-community decision, i.e. all nodes and the supernode need to have it enabled. However, the supernode supports encrpyted and unencrypted communities in parallel, it determines their status online at arrival of the first packet. Use a fresh community name for encrypted communities; do not use a previously used one of former unecrpyted communities: their names were transmitted openly.
172
173### Checksum
174
175The whole packet including the eventually present payload is checksummed using a modified Person hashing. It might seem a little short compared to usual message tags of 96 up to 128 bit, especially when using a stream cipher which easily allows for bit-flips. So, the 16-bit checksum is filled up with 80 more bits to obtain a 96-bit pre-IV. This pre-IV gets encrypted using a single block-cipher step to get the pseudo-random looking IV. This way, the checksum resists targeted bit-flips (to header, payload, and IV) as any change to the whole 96-bit IV would render the header un-decryptable.
176
177The single block-cipher step employs SPECK because it is fast, always present as built-in and it offers a 96-bit version. The key is derived from the header key – a hash of the hash.
178
179The checksum gets verified by the edges and the supernode.
180
181### Replay Protection
182
183The aforementioned fill-up does not completely rely on random bits. A 52-bit time stamp displaying a microsecond-accuracy is encoded to the 96-bit pre-IV as well:
184
185```
186    012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345
187   +------------------------------------------------------------------------------------------------+
188   !     52-bit time stamp with microsecond-accuracy    ! 28 pseudo-random bits     !16-bit checksum!
189   +------------------------------------------------------------------------------------------------+
190
191```
192Encrypting this pre-IV with a block cipher step will generate a pseudo-random looking IV which gets written to the packet and used for the header encryption.
193
194Due to the time-stamp encoded, the IV will more likely be unique, close to a real nonce.
195
196Upon receival, the time stamp as well as the checksum can be extracted from the IV by performing a 96-bit block-cipher decryption step. Verification of the time stamp happens in two steps:
197
198- The (remote) time stamp is checked against the local clock. It may not deviate more than plus/minus 16 seconds. So, edges and supernode need to keep a somewhat current time. This limit can be adjusted by changing the `TIME_STAMP_FRAME` definition. It is time-zone indifferent as UTC is used.
199
200- Valid (remote) time stamps get stored as "last valid time stamp" seen from each node (supernode and edges). So, a newly arriving packet's time stamp can be compared to the last valid one. It should be equal or higher. However, as UDP packets may overtake each other just by taking another path through the internet, they are allowed to be 160 millisecond earlier than the last valid one. This limit can be adjusted by changing the `TIME_STAMP_JITTER` definition.
201
202The way the IV is used for replay protection and for checksumming makes enabled header encryption a prerequisite for these features.
203