Home | History | Annotate | Download | only in openssh
      1 This document describes the chacha20-poly1305 (a] 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 (a] 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 (a] openssh.com offers both encryption and
     26 authentication. As such, no separate MAC is required. If the
     27 chacha20-poly1305 (a] 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 (a] 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 The first 256 bits consitute K_2 and the second 256 bits become
     38 K_1.
     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
     52 its MAC (assuming key derivation, ChaCha20 and Poly1305 are secure).
     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 (a] 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 
    106 $OpenBSD: PROTOCOL.chacha20poly1305,v 1.3 2016/05/03 13:10:24 djm Exp $
    107 
    108