Damien Miller | 0fde8ac | 2013-11-21 14:12:23 +1100 | [diff] [blame] | 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. |
djm@openbsd.org | 05855bf | 2016-05-03 13:10:24 +0000 | [diff] [blame] | 37 | The first 256 bits consitute K_2 and the second 256 bits become |
| 38 | K_1. |
Damien Miller | 0fde8ac | 2013-11-21 14:12:23 +1100 | [diff] [blame] | 39 | |
| 40 | The instance keyed by K_1 is a stream cipher that is used only |
| 41 | to encrypt the 4 byte packet length field. The second instance, |
| 42 | keyed by K_2, is used in conjunction with poly1305 to build an AEAD |
| 43 | (Authenticated Encryption with Associated Data) that is used to encrypt |
| 44 | and authenticate the entire packet. |
| 45 | |
| 46 | Two separate cipher instances are used here so as to keep the packet |
| 47 | lengths confidential but not create an oracle for the packet payload |
| 48 | cipher by decrypting and using the packet length prior to checking |
| 49 | the MAC. By using an independently-keyed cipher instance to encrypt the |
| 50 | length, an active attacker seeking to exploit the packet input handling |
| 51 | as a decryption oracle can learn nothing about the payload contents or |
Damien Miller | 114e540 | 2013-12-05 10:22:57 +1100 | [diff] [blame] | 52 | its MAC (assuming key derivation, ChaCha20 and Poly1305 are secure). |
Damien Miller | 0fde8ac | 2013-11-21 14:12:23 +1100 | [diff] [blame] | 53 | |
| 54 | The AEAD is constructed as follows: for each packet, generate a Poly1305 |
| 55 | key by taking the first 256 bits of ChaCha20 stream output generated |
| 56 | using K_2, an IV consisting of the packet sequence number encoded as an |
| 57 | uint64 under the SSH wire encoding rules and a ChaCha20 block counter of |
| 58 | zero. The K_2 ChaCha20 block counter is then set to the little-endian |
| 59 | encoding of 1 (i.e. {1, 0, 0, 0, 0, 0, 0, 0}) and this instance is used |
| 60 | for encryption of the packet payload. |
| 61 | |
| 62 | Packet Handling |
| 63 | --------------- |
| 64 | |
| 65 | When receiving a packet, the length must be decrypted first. When 4 |
| 66 | bytes of ciphertext length have been received, they may be decrypted |
| 67 | using the K_1 key, a nonce consisting of the packet sequence number |
| 68 | encoded as a uint64 under the usual SSH wire encoding and a zero block |
| 69 | counter to obtain the plaintext length. |
| 70 | |
| 71 | Once the entire packet has been received, the MAC MUST be checked |
| 72 | before decryption. A per-packet Poly1305 key is generated as described |
| 73 | above and the MAC tag calculated using Poly1305 with this key over the |
| 74 | ciphertext of the packet length and the payload together. The calculated |
| 75 | MAC is then compared in constant time with the one appended to the |
| 76 | packet and the packet decrypted using ChaCha20 as described above (with |
| 77 | K_2, the packet sequence number as nonce and a starting block counter of |
| 78 | 1). |
| 79 | |
| 80 | To send a packet, first encode the 4 byte length and encrypt it using |
| 81 | K_1. Encrypt the packet payload (using K_2) and append it to the |
| 82 | encrypted length. Finally, calculate a MAC tag and append it. |
| 83 | |
| 84 | Rekeying |
| 85 | -------- |
| 86 | |
| 87 | ChaCha20 must never reuse a {key, nonce} for encryption nor may it be |
| 88 | used to encrypt more than 2^70 bytes under the same {key, nonce}. The |
| 89 | SSH Transport protocol (RFC4253) recommends a far more conservative |
| 90 | rekeying every 1GB of data sent or received. If this recommendation |
| 91 | is followed, then chacha20-poly1305@openssh.com requires no special |
| 92 | handling in this area. |
| 93 | |
| 94 | References |
| 95 | ---------- |
| 96 | |
| 97 | [1] "ChaCha, a variant of Salsa20", Daniel Bernstein |
| 98 | http://cr.yp.to/chacha/chacha-20080128.pdf |
| 99 | |
| 100 | [2] "The Poly1305-AES message-authentication code", Daniel Bernstein |
| 101 | http://cr.yp.to/mac/poly1305-20050329.pdf |
| 102 | |
| 103 | [3] "ChaCha20 and Poly1305 based Cipher Suites for TLS", Adam Langley |
| 104 | http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-03 |
| 105 | |
djm@openbsd.org | 05855bf | 2016-05-03 13:10:24 +0000 | [diff] [blame] | 106 | $OpenBSD: PROTOCOL.chacha20poly1305,v 1.3 2016/05/03 13:10:24 djm Exp $ |
Damien Miller | 0fde8ac | 2013-11-21 14:12:23 +1100 | [diff] [blame] | 107 | |