1 |
This document describes the chacha20-poly1305@openssh.com authenticated |
2 |
encryption cipher supported by OpenSSH. |
3 |
|
4 |
Background |
5 |
---------- |
6 |
|
7 |
ChaCha20 is a stream cipher designed by Daniel Bernstein and described |
8 |
in [1]. It operates by permuting 128 fixed bits, 128 or 256 bits of key, |
9 |
a 64 bit nonce and a 64 bit counter into 64 bytes of output. This output |
10 |
is used as a keystream, with any unused bytes simply discarded. |
11 |
|
12 |
Poly1305[2], also by Daniel Bernstein, is a one-time Carter-Wegman MAC |
13 |
that computes a 128 bit integrity tag given a message and a single-use |
14 |
256 bit secret key. |
15 |
|
16 |
The chacha20-poly1305@openssh.com combines these two primitives into an |
17 |
authenticated encryption mode. The construction used is based on that |
18 |
proposed for TLS by Adam Langley in [3], but differs in the layout of |
19 |
data passed to the MAC and in the addition of encyption of the packet |
20 |
lengths. |
21 |
|
22 |
Negotiation |
23 |
----------- |
24 |
|
25 |
The chacha20-poly1305@openssh.com offers both encryption and |
26 |
authentication. As such, no separate MAC is required. If the |
27 |
chacha20-poly1305@openssh.com cipher is selected in key exchange, |
28 |
the offered MAC algorithms are ignored and no MAC is required to be |
29 |
negotiated. |
30 |
|
31 |
Detailed Construction |
32 |
--------------------- |
33 |
|
34 |
The chacha20-poly1305@openssh.com cipher requires 512 bits of key |
35 |
material as output from the SSH key exchange. This forms two 256 bit |
36 |
keys (K_1 and K_2), used by two separate instances of chacha20. |
37 |
|
38 |
The instance keyed by K_1 is a stream cipher that is used only |
39 |
to encrypt the 4 byte packet length field. The second instance, |
40 |
keyed by K_2, is used in conjunction with poly1305 to build an AEAD |
41 |
(Authenticated Encryption with Associated Data) that is used to encrypt |
42 |
and authenticate the entire packet. |
43 |
|
44 |
Two separate cipher instances are used here so as to keep the packet |
45 |
lengths confidential but not create an oracle for the packet payload |
46 |
cipher by decrypting and using the packet length prior to checking |
47 |
the MAC. By using an independently-keyed cipher instance to encrypt the |
48 |
length, an active attacker seeking to exploit the packet input handling |
49 |
as a decryption oracle can learn nothing about the payload contents or |
50 |
its MAC (assuming key derivation, ChaCha20 and Poly1305 are secure). |
51 |
|
52 |
The AEAD is constructed as follows: for each packet, generate a Poly1305 |
53 |
key by taking the first 256 bits of ChaCha20 stream output generated |
54 |
using K_2, an IV consisting of the packet sequence number encoded as an |
55 |
uint64 under the SSH wire encoding rules and a ChaCha20 block counter of |
56 |
zero. The K_2 ChaCha20 block counter is then set to the little-endian |
57 |
encoding of 1 (i.e. {1, 0, 0, 0, 0, 0, 0, 0}) and this instance is used |
58 |
for encryption of the packet payload. |
59 |
|
60 |
Packet Handling |
61 |
--------------- |
62 |
|
63 |
When receiving a packet, the length must be decrypted first. When 4 |
64 |
bytes of ciphertext length have been received, they may be decrypted |
65 |
using the K_1 key, a nonce consisting of the packet sequence number |
66 |
encoded as a uint64 under the usual SSH wire encoding and a zero block |
67 |
counter to obtain the plaintext length. |
68 |
|
69 |
Once the entire packet has been received, the MAC MUST be checked |
70 |
before decryption. A per-packet Poly1305 key is generated as described |
71 |
above and the MAC tag calculated using Poly1305 with this key over the |
72 |
ciphertext of the packet length and the payload together. The calculated |
73 |
MAC is then compared in constant time with the one appended to the |
74 |
packet and the packet decrypted using ChaCha20 as described above (with |
75 |
K_2, the packet sequence number as nonce and a starting block counter of |
76 |
1). |
77 |
|
78 |
To send a packet, first encode the 4 byte length and encrypt it using |
79 |
K_1. Encrypt the packet payload (using K_2) and append it to the |
80 |
encrypted length. Finally, calculate a MAC tag and append it. |
81 |
|
82 |
Rekeying |
83 |
-------- |
84 |
|
85 |
ChaCha20 must never reuse a {key, nonce} for encryption nor may it be |
86 |
used to encrypt more than 2^70 bytes under the same {key, nonce}. The |
87 |
SSH Transport protocol (RFC4253) recommends a far more conservative |
88 |
rekeying every 1GB of data sent or received. If this recommendation |
89 |
is followed, then chacha20-poly1305@openssh.com requires no special |
90 |
handling in this area. |
91 |
|
92 |
References |
93 |
---------- |
94 |
|
95 |
[1] "ChaCha, a variant of Salsa20", Daniel Bernstein |
96 |
http://cr.yp.to/chacha/chacha-20080128.pdf |
97 |
|
98 |
[2] "The Poly1305-AES message-authentication code", Daniel Bernstein |
99 |
http://cr.yp.to/mac/poly1305-20050329.pdf |
100 |
|
101 |
[3] "ChaCha20 and Poly1305 based Cipher Suites for TLS", Adam Langley |
102 |
http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-03 |
103 |
|
104 |
$OpenBSD: PROTOCOL.chacha20poly1305,v 1.2 2013/12/02 02:50:27 djm Exp $ |
105 |
|