<?xml version="1.0"?>

<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
<!ENTITY rfc4253 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.4253.xml">
<!ENTITY TLSCP PUBLIC '' 'http://xml2rfc.ietf.org/public/rfc/bibxml3/reference.I-D.agl-tls-chacha20poly1305.xml'>
]>

<?rfc compact="yes"?>
<?rfc toc="yes"?>
<?rfc symrefs="yes"?>

<rfc category="info" ipr="trust200902"
     docName="draft-josefsson-ssh-chacha20-poly1305-openssh-01">

  <front>

    <title abbrev="SSH chacha20-poly1305">
      Secure Shell (SSH) authenticated encryption cipher:
      chacha20-poly1305
    </title>
    
    <author initials="D." surname="Miller" fullname="Damien Miller">
      <organization>OpenSSH</organization>
      <address>
        <email>djm@mindrot.org</email>
      </address>
    </author>

    <author initials="S." surname="Josefsson" fullname="Simon Josefsson">
      <organization>SJD AB</organization>
      <address>
	<email>simon@josefsson.org</email>
      </address>
    </author>

    <date month="August" year="2024" day="21"/>

    <abstract>

      <t>
	This document describes the Secure Shell (SSH)
	chacha20-poly1305 authenticated encryption cipher.
      </t>

    </abstract>

  </front>
  
  <middle>

    <section title="Introduction">

      <t>
	ChaCha20 is a stream cipher designed by Daniel Bernstein and
	described in <xref target="ChaCha" />.  It operates by
	permuting 128 fixed bits, 128 or 256 bits of key, a 64 bit
	nonce and a 64 bit counter into 64 bytes of output.  This
	output is used as a keystream, with any unused bytes simply
	discarded.
      </t>

      <t>
	<xref target="Poly1305">Poly1305</xref>, also by Daniel
	Bernstein, is a one-time Carter-Wegman MAC that computes a 128
	bit integrity tag given a message and a single-use 256 bit
	secret key.
      </t>
      
      <t>
	The "chacha20-poly1305" cipher combines these two
	primitives into an authenticated encryption mode.  The
	construction used is based on that proposed for TLS by Adam
	Langley in <xref target="I-D.agl-tls-chacha20poly1305"/>, but
	differs in the layout of data passed to the MAC and in the
	addition of encyption of the packet lengths.
      </t>

      <t>
	This document specify and register "chacha20-poly1305" to be
	identical to the already widely deployed
	"chacha20-poly1305@openssh.com".</t>

    </section>

    <section title="Negotiation">

      <t>
	The "chacha20-poly1305" offers both encryption and
	authentication. As such, no separate MAC is required. If the
	"chacha20-poly1305" cipher is selected in key exchange, the
	offered MAC algorithms are ignored and no MAC is required to
	be negotiated.
      </t>

    </section>

    <section title="Detailed Construction">

      <t>
	The "chacha20-poly1305" cipher requires 512 bits of key
	material as output from the SSH key exchange. This forms two
	256 bit keys (K_1 and K_2), used by two separate instances of
	chacha20.
      </t>

      <t>
	The instance keyed by K_1 is a stream cipher that is used only
	to encrypt the 4 byte packet length field. The second
	instance, keyed by K_2, is used in conjunction with poly1305
	to build an AEAD (Authenticated Encryption with Associated
	Data) that is used to encrypt and authenticate the entire
	packet.
      </t>

      <t>
	Two separate cipher instances are used here so as to keep the
	packet lengths confidential but not create an oracle for the
	packet payload cipher by decrypting and using the packet
	length prior to checking the MAC. By using an
	independently-keyed cipher instance to encrypt the length, an
	active attacker seeking to exploit the packet input handling
	as a decryption oracle can learn nothing about the payload
	contents or its MAC (assuming key derivation, ChaCha20 and
	Poly1305 are secure).
      </t>

      <t>
	The AEAD is constructed as follows: for each packet, generate
	a Poly1305 key by taking the first 256 bits of ChaCha20 stream
	output generated using K_2, an IV consisting of the packet
	sequence number encoded as an uint64 under the SSH wire
	encoding rules and a ChaCha20 block counter of zero. The K_2
	ChaCha20 block counter is then set to the little-endian
	encoding of 1 (i.e. {1, 0, 0, 0, 0, 0, 0, 0}) and this
	instance is used for encryption of the packet payload.
      </t>

    </section>

    <section title="Packet Handling">

      <t>
	When receiving a packet, the length must be decrypted
	first. When 4 bytes of ciphertext length have been received,
	they may be decrypted using the K_1 key, a nonce consisting of
	the packet sequence number encoded as a uint64 under the usual
	SSH wire encoding and a zero block counter to obtain the
	plaintext length.
      </t>
      
      <t>
	Once the entire packet has been received, the MAC MUST be
	checked before decryption. A per-packet Poly1305 key is
	generated as described above and the MAC tag calculated using
	Poly1305 with this key over the ciphertext of the packet
	length and the payload together. The calculated MAC is then
	compared in constant time with the one appended to the packet
	and the packet decrypted using ChaCha20 as described above
	(with K_2, the packet sequence number as nonce and a starting
	block counter of 1).
      </t>

      <t>
	To send a packet, first encode the 4 byte length and encrypt
	it using K_1. Encrypt the packet payload (using K_2) and
	append it to the encrypted length. Finally, calculate a MAC
	tag and append it.
      </t>
      
    </section>

    <section title="Rekeying">

      <t>
	ChaCha20 must never reuse a {key, nonce} for encryption nor
	may it be used to encrypt more than 2^70 bytes under the same
	{key, nonce}. The <xref target="RFC4253">SSH Transport
	protocol</xref> recommends a far more conservative rekeying
	every 1GB of data sent or received.  If this recommendation is
	followed, then "chacha20-poly1305" requires no special
	handling in this area.
      </t>
      
    </section>
    
    <section title="Acknowledgements">

      <t>
	Markus Friedl helped on the design.  Theo de Raadt supported
	to register the OpenSSH private-use cipher for generic use.
      </t>

    </section>

    <section>

      <name>IANA Considerations</name>

      <t>
	IANA is requested to add a new "Encryption Algorithm Name" of
	"chacha20-poly1305" the "Encryption Algorithm Names" registry
	for Secure Shell (SSH) Protocol Parameters <xref
	target="IANA-ENCALG" format="default" sectionFormat="of"
	derivedContent="IANA-ENCALG"/> with a "Reference" field
	referring this RFC.
      </t>

    </section>

  </middle>

  <back>

    <references title="Normative References">

      &rfc4253;

      <reference anchor="IANA-ENCALG" target="https://www.iana.org/assignments/ssh-parameters/"
		 quoteTitle="true" derivedAnchor="IANA-ENCALG">
        <front>
          <title>Secure Shell (SSH) Protocol Parameters: Encryption
          Algorithm Names</title>
          <author>
            <organization showOnFrontPage="true">IANA</organization>
          </author>
          <date/>
        </front>
      </reference>

    </references>

    <references title="Informative References">

      &TLSCP;

      <reference anchor="ChaCha"
		 target="http://cr.yp.to/chacha/chacha-20080128.pdf">
	<front>
          <title>
            ChaCha, a variant of Salsa20
          </title>
          <author surname="Bernstein" initials="J."
                  fullname="Daniel J. Bernstein">
            <organization></organization>
          </author>
          <date month="January" year="2008"/>
	</front>
      </reference>

      <reference anchor="Poly1305"
		 target="http://cr.yp.to/mac/poly1305-20050329.pdf">
	<front>
          <title>
            The Poly1305-AES message-authentication code
          </title>
          <author surname="Bernstein" initials="J."
                  fullname="Daniel J. Bernstein">
            <organization></organization>
          </author>
          <date month="March" year="2005"/>
	</front>
      </reference>

    </references>

  </back>

</rfc>
