<?xml version="1.0"?>

<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
<!ENTITY rfc4253 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.4253.xml">
<!ENTITY STRICTKEX PUBLIC '' 'http://xml2rfc.ietf.org/public/rfc/bibxml3/reference.I-D.miller-sshm-strict-kex.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="std" ipr="trust200902"
     consensus="true"
     docName="draft-ietf-sshm-chacha20-poly1305-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.G." surname="Tatham" fullname="Simon Tatham">
      <organization abbrev="PuTTY">PuTTY</organization>
      <address>
        <email>anakin@pobox.com</email>
      </address>
    </author>

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

    <date month="March" year="2025" day="17"/>

    <abstract>

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

    </abstract>

    <note>
      <t>
        This document is UNFINISHED. Before publication as an RFC, it
        must no longer contain any instance of the string "FIXME",
        which is used to mark where required information has not yet
        been added.
      </t>
    </note>

  </front>
  
  <middle>

    <section title="Introduction">

      <t>
	ChaCha20 is a stream cipher designed by Daniel Bernstein and
	described in <xref target="ChaCha" />, with some details
	inherited from <xref target="Salsa20" />. 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 encryption of the packet lengths.
        In particular, the key generation for Poly1305 is based on
        ChaCha20, instead of AES as described in <xref
        target="Poly1305" />.
      </t>

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

    </section>

    <section title="ChaCha20">

      <t>
        ChaCha20 is defined by two long documents, but the actual
        cipher definition is simple enough to restate the full
        specification here.
      </t>

      <t>
        ChaCha20 operates on an array of sixteen 32-bit integers,
        usually written in the form of a square matrix, with x[0],
        ..., x[3] on the top row, ..., x[12], ..., x[15] on the bottom
        row.
      </t>

      <t>
        The ChaCha20 permutation is a fixed, keyless transformation
        which turns an input matrix into an output one. It is
        described in full by the following pseudocode, in which
        addition is modulo 2^32, and ROL describes bitwise left
        rotation of 32-bit integers:
      </t>

      <figure anchor="chacha20" title="Pseudocode of the ChaCha20 transform">
        <artwork>
one_16th_of_a_round(matrix, p, q, r, rotation):
    matrix[p] &lt;- matrix[p] + matrix[q]
    matrix[r] &lt;- (matrix[r] XOR matrix[p]) ROL rotation

one_quarter_of_a_round(matrix, a, b, c, d):
    one_16th_of_a_round(matrix, a, b, d, 16)
    one_16th_of_a_round(matrix, c, d, b, 12)
    one_16th_of_a_round(matrix, a, b, d, 8)
    one_16th_of_a_round(matrix, c, d, b, 7)

even_numbered_round(matrix):
    one_quarter_of_a_round(matrix, 0, 4,  8, 12)
    one_quarter_of_a_round(matrix, 1, 5,  9, 13)
    one_quarter_of_a_round(matrix, 2, 6, 10, 14)
    one_quarter_of_a_round(matrix, 3, 7, 11, 15)

odd_numbered_round(matrix):
    one_quarter_of_a_round(matrix, 0, 5, 10, 15)
    one_quarter_of_a_round(matrix, 1, 6, 11, 12)
    one_quarter_of_a_round(matrix, 2, 7,  8, 13)
    one_quarter_of_a_round(matrix, 3, 4,  9, 14)

chacha20(matrix):
    orig &lt;- copy(matrix)
    repeat 10 times:
        even_numbered_round(matrix)
        odd_numbered_round(matrix)
    matrix = matrix + orig   // element-wise addition of two matrices
        </artwork>
      </figure>

      <t>
        To generate a ChaCha20 cipher block, the first four words
        x[0],...,x[3] of the input matrix are initialized to fixed
        values obtained by encoding the string "expand 32-byte k" in
        ASCII and interpreting those 16 bytes as the little-endian
        encoding of four 32-bit integers. The next 8 words
        x[4],...,x[11] are initialized from the 32-byte cipher key in
        the same fashion. The next 2 words x[12],x[13] are a 64-bit
        counter which is incremented for each output data block, with
        x[12] being the low-order 32 bits of the counter and x[13] the
        high-order bits. The final 2 words x[14],x[15] are initialized
        from an 8-byte "nonce" which must be a unique identifier for
        each separate message encrypted with the same key.
      </t>

      <t>
        To create a full ChaCha20 cipher stream, a succession of input
        matrices is constructed as above, incrementing the 64-bit
        block counter by 1 in each matrix. Each input matrix is
        independently transformed via the permutation described above,
        and the output matrix is converted into 64 bytes of cipher
        stream by encoding each 32-bit integer little-endian. Generate
        as many blocks of the cipher stream as necessary; XOR the
        cipher stream byte-wise into the message to be encrypted;
        discard any remaining part of the final block.
      </t>

    </section>

    <section title="Poly1305">

      <t>
        The Poly1305 authenticator used in this specification differs
        from the description in <xref target="Poly1305" /> in how it
        generates the key material, so it is convenient to specify
        that in full here as well.
      </t>

      <t>
        Poly1305 as described here requires two 16-byte key inputs.
        Each one is interpreted as the little-endian encoding of a
        128-bit integer. One of these integers is then bitwise-ANDed
        with the integer 0x0FFFFFFC0FFFFFFC0FFFFFFC0FFFFFFF, and the
        result is denoted as 'r'. The other integer is denoted as 'n',
        and requires no modification.
      </t>

      <t>
        The input message to be authenticated is divided into blocks
        of 16 bytes, with a short block at the end if its length is
        not a multiple of 16. Each block is converted into an integer
        of size up to 2^129, by appending the byte 0x01 and then
        interpreting the extended block as the little-endian encoding
        of an integer. (So all the resulting integers have bit 128
        set, except that if there is a final short block of s &lt; 16
        bytes, then that integer will have bit (8*s) set.)
      </t>

      <t>
        Denote the message integers as C[1], C[2], ..., C[m]. Then the
        MAC is computed as follows.
      </t>

      <t>
        Perform a polynomial evaluation in which the variable is the
        key integer 'r'; the constant coefficient is zero; the
        coefficient of r^1 is c[m], the coefficient of r^2 is c[m-1],
        ..., and the coefficient of r^m is c[1]. This can be achieved
        by initializing an accumulator A to zero, and then for each
        coefficient c[i], in turn, setting A &lt;- (A + c[i]) * r.
      </t>

      <t>
        The result of this evaluation is reduced modulo 2^130-5 to
        give the least non-negative residue. (It follows that the
        intermediate results of the polynomial evaluation can be
        reduced in the same way, without affecting the output.) That
        residue is then reduced again modulo 2^128, and added modulo
        2^128 to the other key integer 'n'. This final 128-bit integer
        is encoded little-endian and forms the output authentication
        tag.
      </t>

      <t>
        In the original specification <xref target="Poly1305" />, the
        key provided by the application consists of 16 bytes of data
        used to create 'r' as described above, and another 16 bytes
        used as an AES key to encrypt a per-message nonce, with the
        ciphertext being used to create 'n'. So 'r' is reused between
        messages, with only 'n' changing. However, in this
        specification, both 'r' and 'n' are created from parts of the
        output of the same ChaCha20 transformation, as described
        below. So both values change in every message.
      </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 the second half of the key material,
	K_2, is a stream cipher that is used only to encrypt the 4
	byte packet length field. The instance keyed by the first half
	K_1 is used to encrypt the remainder of the packet. The
	concatenated ciphertext from both of these operations is then
	authenticated using Poly1305 with a key derived from the K_1
	cipher stream.
      </t>

      <t>
        The 8-byte nonce required by ChaCha20 is obtained by encoding
        the SSH packet sequence number as a 64-bit integer, in the
        usual SSH big-endian encoding. Since the SSH packet sequence
        number is defined to be a 32-bit integer, this means that the
        first four bytes of the ChaCha20 nonce, creating the input
        matrix entry x[14], are always zero. The second four bytes are
        the big-endian encoding of the SSH sequence number, which
        means that the matrix entry x[15] is the sequence number with
        its byte order reversed, because that results from decoding
        the same four bytes little-endian.
      </t>

      <t>
        For the K_2 cipher instance that encrypts the length, the
        block counter is always 0, because only one block is needed
        (and only the first four bytes of that block are used). For
        the K_1 cipher instance used for the packet payload, the block
        counter value starts at 1 and increments to generate the
        cipher stream that encrypts the packet.
      </t>

      <t>
	To generate keying information for the Poly1305 MAC, the K_1
	cipher instance is run with the same key and nonce but a block
	counter value of 0. The first 16 bytes of the output are
	converted into the Poly1305 key integer 'r' at which the
	polynomial is evaluated, by decoding them as a 128-bit
	little-endian integer and clearing certain bits of that
	integer as described in <xref target="Poly1305" />. The second
	16 bytes are converted into the mask integer 'n' added at the
	end of the Poly1305 algorithm.
      </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_2 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_1, 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_2. Encrypt the packet payload (using K_1) 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 title="Security Considerations">

      <t>
        The use of this cipher and MAC combination has a KNOWN
        SECURITY VULNERABILITY. This specification modifies the SSH
        binary packet protocol in a way that makes the encryption and
        authentication of every packet independent: instead of
        generating a single continuous cipher stream and dividing it
        at packet boundaries, a fresh cipher stream is started for
        each packet based on that packet's sequence number. This makes
        it possible for a MITM attacker to delete an entire packet
        from one direction of the SSH data stream, if they can
        manipulate the receiving end's idea of the packet sequence
        number. In the <xref target="Terrapin">"Terrapin"
        attack</xref> (CVE-2023-48795), this is achieved by combining
        deletion of the first encrypted packet with injection of an
        earlier SSH_MSG_IGNORE packet, in the cleartext segment of the
        SSH session before the initial key exchange completes. The
        injected and deleted packets have opposite effects on the
        sequence number and cancel one another out, so that the
        receiving side uses the correct sequence number to decrypt the
        first remaining packet in the cipher stream, and never detects
        the modification. This is a breach of the SSH transport
        protocol's security guarantee.
      </t>

      <t>
        Implementations deploying the "chacha20-poly1305" cipher and
        MAC combination MUST support a means of mitigating this
        attack, and deploy the mitigation if the other end of the SSH
        connection is also capable of doing so.
      </t>

      <t>
        As of 2025, a mitigation commonly deployed is called <xref
        target="I-D.miller-sshm-strict-kex">Strict KEX</xref>. In this
        modification, the packet sequence number used for
        cryptographic purposes is reset to 0 immediately after each
        SSH_MSG_NEWKEYS, and extraneous packets such as SSH_MSG_IGNORE
        are prohibited in the initial cleartext segment of the
        session.
      </t>

      <t>
        On the other hand, the use of two separate cipher instances is
        itself a mitigation for another family of attacks found in SSH
        (e.g. CVE-2008-5161), in which an attacker uses the fact that
        the receiver acts on the decrypted length before checking the
        MAC, to obtain an oracle for the packet payload cipher by
        modifying the packet length field and observing the receiver's
        response. In this protocol, the length is encrypted using an
        independently-keyed cipher, so any attempt to exploit the
        decryption of the length field only gains information about
        the length cipher, and not about the separate cipher instance
        that encrypts the packet payload.
      </t>

      <t>
        In the original specification for Poly1305, the nonce value
        added to the result of the polynomial evaluation was generated
        by AES. In this specification, ChaCha20 is used instead
        because [FIXME: presumably "it seemed silly to use two
        ciphers"]. This is believed not to negatively impact security
        because [FIXME: presumably something to do with the security
        proof in Poly1305].
      </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 and the "OK to implement" field of "MUST".
      </t>

    </section>

  </middle>

  <back>

    <references title="Normative References">

      &rfc4253;

      &STRICTKEX;

      <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="Salsa20"
		 target="http://cr.yp.to/snuffle/salsafamily-20071225.pdf">
	<front>
          <title>
            The Salsa20 family of stream ciphers
          </title>
          <author surname="Bernstein" initials="J."
                  fullname="Daniel J. Bernstein">
            <organization></organization>
          </author>
          <date month="December" year="2007"/>
	</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>

      <reference anchor="Terrapin"
                 target="https://arxiv.org/abs/2312.12422">
        <front>
          <title>
            Terrapin Attack: Breaking SSH Channel Integrity By
            Sequence Number Manipulation
          </title>
          <author surname="Bäumer" fullname="Fabian Bäumer">
            <organization>Ruhr University Bochum</organization>
          </author>
          <author surname="Brinkmann" fullname="Marcus Brinkmann">
            <organization>Ruhr University Bochum</organization>
          </author>
          <author surname="Schwenk" fullname="Jörg Schwenk">
            <organization>Ruhr University Bochum</organization>
          </author>
          <date month="December" year="2023"/>
        </front>
      </reference>

    </references>

  <section title="Worked Example">

    <t>
      Since this specification modifies both Poly1305 (by generating
      its key data using a different cipher) and the SSH binary packet
      protocol, it is useful to present a full example of how an SSH
      packet is encrypted and authenticated to generate the exact data
      sent over the network.
    </t>

    <t>
      The example input packet, described using the conventional SSH
      marshalling notation, is as follows:
    </t>

    <figure anchor="input.log" title="Logical form of the input packet">
      <artwork>
byte      0x5e (SSH2_MSG_CHANNEL_DATA)
uint32    0 (recipient channel id)
string    "Lorem ipsum dolor sit amet, consectetur adipisicing elit"
      </artwork>
    </figure>

    <t>
      After encoding in the binary packet protocol, this becomes the
      following data:
    </t>

    <figure anchor="input.packet" title="Full encoding of the input packet before encryption">
      <artwork>
uint32    0x48 (packet length not including this field)
byte      0x06 (number of bytes of padding)
byte      0x5e (SSH2_MSG_CHANNEL_DATA)
uint32    0 (recipient channel id)
string    "Lorem ipsum dolor sit amet, consectetur adipisicing elit"
byte[6]   0x4e 0x43 0xe8 0x04 0xdc 0x6c (random padding bytes)
      </artwork>
    </figure>

    <t>
      which in turn is encoded into the following bytes:
    </t>

    <figure anchor="input.clearhex" title="Input packet encoded as hex bytes, before encryption">
      <artwork>
00 00 00 48  06 5e 00 00  00 00 00 00  00 38 4c 6f
72 65 6d 20  69 70 73 75  6d 20 64 6f  6c 6f 72 20
73 69 74 20  61 6d 65 74  2c 20 63 6f  6e 73 65 63
74 65 74 75  72 20 61 64  69 70 69 73  69 63 69 6e
67 20 65 6c  69 74 4e 43  e8 04 dc 6c
      </artwork>
    </figure>

    <t>
      In this example connection, this packet was sent from client to
      server, with a sequence number of 7.
    </t>

    <t>
      The encryption key for the client-to-server direction of the
      connection, derived as specified in RFC4253 section 7.2, is 64
      bytes long and consists of the following bytes:
    </t>

    <figure anchor="key.bytes" title="Key material output from the key exchange">
      <artwork>
8b bf f6 85  5f c1 02 33  8c 37 3e 73  aa c0 c9 14
f0 76 a9 05  b2 44 4a 32  ee ca ff ea  e2 2b ec c5
e9 b7 a7 a5  82 5a 82 49  34 6e c1 c2  83 01 cf 39
45 43 fc 75  69 88 7d 76  e1 68 f3 75  62 ac 07 40
      </artwork>
    </figure>

    <t>
      To encrypt the first 4 bytes of the packet, consisting of the
      length, the following matrix of 32-bit integers is constructed
      as input to the ChaCha20 permutation, with the key material
      derived from the second half of the above block, and a block
      counter value of 0. (Note that the packet sequence number, in
      the bottom right corner, has been endianness-swapped as a result
      of encoding it big-endian in the SSH convention and then
      decoding it little-endian in the ChaCha20 convention.)
    </t>

    <figure anchor="cipher.length.preimage" title="ChaCha20 preimage matrix for encrypting the packet length">
      <artwork>
0x61707865  0x3320646e  0x79622d32  0x6b206574
0xa5a7b7e9  0x49825a82  0xc2c16e34  0x39cf0183
0x75fc4345  0x767d8869  0x75f368e1  0x4007ac62
0x00000000  0x00000000  0x00000000  0x07000000
      </artwork>
    </figure>

    <t>
      After the ChaCha20 transformation, the output matrix is as
      follows:
    </t>

    <figure anchor="cipher.length.output" title="ChaCha20 output matrix for encrypting the packet length">
      <artwork>
0xaccc3e2c  0xf62f4341  0x94f7b07b  0xe6f481fb
0x75306ddf  0x8b82a326  0x5b1aec13  0x119ff043
0x0ae8ba12  0x1cb72290  0xb1565876  0xf5fee756
0x8ea9bef4  0x6ae96e0d  0x32148e17  0xf9531ec9
      </artwork>
    </figure>

    <t>
      To encrypt the 32-bit length field, only 32 bits of this cipher
      stream are required. The first word, 0xaccc3e2c, is encoded
      little-endian into the four bytes 2c 3e cc ac, and these are
      XORed with the big-endian SSH length field 00 00 00 48 to
      produce the encrypted length field 2c 3e cc e4.
    </t>

    <figure anchor="encrypted.length" title="Encrypted bytes of the packet length field">
      <artwork>
2c 3e cc e4
      </artwork>
    </figure>


    <t>
      The remaining 60 bytes of this output block are discarded. When
      encrypting the length field of the next packet, a fresh data
      block will be generated using that packet's sequence number.
    </t>

    <t>
      To encrypt the remainder of the packet, two cipher blocks are
      required. These are generated from the first 32 bytes of the
      cipher key data, and have block counter values 1 and 2 (value 0
      is used to generate the MAC input). The two matrices input to
      ChaCha20 are therefore as follows, differing only in the block
      counter at the start of the bottom row:
    </t>

    <figure anchor="cipher.main.preimage" title="ChaCha20 preimage matrices for encrypting the main packet data">
      <artwork>
0x61707865  0x3320646e  0x79622d32  0x6b206574
0x85f6bf8b  0x3302c15f  0x733e378c  0x14c9c0aa
0x05a976f0  0x324a44b2  0xeaffcaee  0xc5ec2be2
0x00000001  0x00000000  0x00000000  0x07000000

0x61707865  0x3320646e  0x79622d32  0x6b206574
0x85f6bf8b  0x3302c15f  0x733e378c  0x14c9c0aa
0x05a976f0  0x324a44b2  0xeaffcaee  0xc5ec2be2
0x00000002  0x00000000  0x00000000  0x07000000
      </artwork>
    </figure>

    <t>
      The ChaCha20 permutation transforms these two matrices into the
      following output blocks:
    </t>

    <figure anchor="cipher.main.output" title="ChaCha20 output matrices for encrypting the main packet data">
      <artwork>
0x8905e2a3  0x7b7af05b  0xa9fa6ea9  0x5cc14cfa
0xc2f3c7ea  0x88a92e6d  0x25b5c029  0xee0caac8
0x57e5cf62  0x54d6a747  0x055c2b83  0x11c56757
0x2c0b08c4  0x02606ea4  0xfea28051  0xee4eabfc

0x69c3a5f4  0xb55efbdd  0x80a9caea  0xf270c0a0
0xa45d5d78  0x0b44d75b  0xf75247b7  0xe14c0e37
0x98039827  0xd8b8e8de  0xbf7035b6  0xc90bef5b
0x33e3c45a  0x51418cf6  0xcafeae62  0x6da70d32
      </artwork>
    </figure>

    <t>
      These blocks are converted back into bytes in little-endian
      encoding, to create 128 bytes of data beginning a3 e2 05 89 ...
      and ending ... 32 0d a7 6d. The 72 bytes of packet data (apart
      from the separately encrypted length field) are XORed with the
      first 72 bytes of this data to produce the following encrypted
      output:
    </t>

    <figure anchor="encrypted.main" title="Encrypted bytes of the packet, excluding the length field">
      <artwork>
a5 bc 05 89  5b f0 7a 7b  a9 56 b6 c6  88 29 ac 7c
83 b7 80 b7  00 0e cd e7  45 af c7 05  bb c3 78 ce
03 a2 80 23  6b 87 b5 3b  ed 58 39 66  23 02 b1 64
b6 28 6a 48  cd 1e 09 71  38 e3 cb 90  9b 8b 2b 82
9d d1 8d 2a  35 ff 82 d9
      </artwork>
    </figure>

    <t>
      in which, for example, the first byte 0xa5 is the bitwise XOR of
      the first cipher stream byte 0xa3 with the byte 0x06 from the
      cleartext packet (indicating the number of padding bytes).
    </t>

    <t>
      The encrypted length field is prefixed to the above, to produce
      the complete 76-byte ciphertext:
    </t>

    <figure anchor="packet.nomac" title="Encrypted bytes of the whole packet, including its length">
      <artwork>
2c 3e cc e4  a5 bc 05 89  5b f0 7a 7b  a9 56 b6 c6
88 29 ac 7c  83 b7 80 b7  00 0e cd e7  45 af c7 05
bb c3 78 ce  03 a2 80 23  6b 87 b5 3b  ed 58 39 66
23 02 b1 64  b6 28 6a 48  cd 1e 09 71  38 e3 cb 90
9b 8b 2b 82  9d d1 8d 2a  35 ff 82 d9
      </artwork>
    </figure>

    <t>
      This ciphertext is the input to the Poly1305 MAC, which is
      computed as follows.
    </t>

    <t>
      The packet data is converted into the following sequence of
      polynomial coefficients, by repeatedly taking a maximum of 16
      bytes from the start of the data, appending the byte 0x01, and
      decoding as a little-endian integer:
    </t>

    <figure anchor="mac.coefficients" title="Poly1305 coefficients derived from the encrypted packet">
      <artwork>
C[1] = 0x1c6b656a97b7af05b8905bca5e4cc3e2c
C[2] = 0x105c7af45e7cd0e00b780b7837cac2988
C[3] = 0x1663958ed3bb5876b2380a203ce78c3bb
C[4] = 0x190cbe33871091ecd486a28b664b10223
C[5] =         0x1d982ff352a8dd19d822b8b9b
      </artwork>
    </figure>

    <t>
      The MAC key is constructed by generating a block of ChaCha20
      cipher stream, using the same cipher that encrypted most of the
      packet, with a block counter value of 0. So the input to the
      ChaCha20 transformation is the following matrix:
    </t>

    <figure anchor="cipher.mac.preimage" title="ChaCha20 preimage matrix for keying the MAC">
      <artwork>
0x61707865  0x3320646e  0x79622d32  0x6b206574
0x85f6bf8b  0x3302c15f  0x733e378c  0x14c9c0aa
0x05a976f0  0x324a44b2  0xeaffcaee  0xc5ec2be2
0x00000000  0x00000000  0x00000000  0x07000000
      </artwork>
    </figure>

    <t>
      and the ChaCha20 permutation transforms it into this:
    </t>

    <figure anchor="cipher.mac.output" title="ChaCha20 output matrix for keying the MAC">
      <artwork>
0xfba86ef6  0x046d187a  0xa6b4d75d  0xa4487348
0xebc13a8f  0xe0be63fa  0x65a5e1c1  0xdd5b9fd0
0x95f6ca26  0x509e2eec  0xb9f34fe2  0xc565e785
0xd52da783  0xc8f24915  0xb3907730  0x1da12e04
      </artwork>
    </figure>

    <t>
      The top row of this matrix is converted into a 128-bit integer
      by recombining the four words in little-endian order, to make
      0xa4487348a6b4d75d046d187afba86ef6. This is transformed into the
      Poly1305 integer 'r' at which the polynomial is evaluated, by
      computing its bitwise AND with the integer
      0x0FFFFFFC0FFFFFFC0FFFFFFC0FFFFFFF. The result is r =
      0x0448734806b4d75c046d18780ba86ef6.
    </t>

    <t>
      The second row of the matrix is similarly converted into a
      128-bit integer 0xdd5b9fd065a5e1c1e0be63faebc13a8f, which is
      used as the mask value 'n' added at the end of the computation.
      The remaining two rows of the ChaCha20 output are discarded.
    </t>

    <t>
      The Poly1305 MAC is constructed by calculating the least
      non-negative residue mod 2^130-5 of the following expression:
    </t>

    <figure anchor="mac.expression" title="Polynomial expression evaluated while computing Poly1305">
      <artwork>
C[1] * r^5 + C[2] * r^4 + C[3] * r^3 + C[4] * r^[2] + C[5] * r
      </artwork>
    </figure>

    <t>
      The output of this computation is the integer
      0x2db8d08018cd015cc486e8c6099dcfa06. This is reduced mod 2^128
      to obtain 0xdb8d08018cd015cc486e8c6099dcfa06, which is then
      added modulo 2^128 to the nonce value
      0xdd5b9fd065a5e1c1e0be63faebc13a8f, giving
      0xb8e8a7d1f275f78e292cf05b859e3495. This is encoded as a 16-bit
      little-endian integer to give the final authentication tag:
    </t>

    <figure anchor="mac.final" title="Bytes of the final Poly1305 authentication tag">
      <artwork>
95 34 9e 85  5b f0 2c 29  8e f7 75 f2  d1 a7 e8 b8
      </artwork>
    </figure>

    <t>
      The full encrypted and authenticated data of this packet, sent
      over the TCP connection to the SSH server, is constructed by
      concatenating the encrypted length field, the rest of the
      encrypted packet data, and the authentication tag, and is as
      follows:
    </t>

    <figure anchor="packet.final" title="Full wire format of the packet, including the MAC">
      <artwork>
2c 3e cc e4  a5 bc 05 89  5b f0 7a 7b  a9 56 b6 c6
88 29 ac 7c  83 b7 80 b7  00 0e cd e7  45 af c7 05
bb c3 78 ce  03 a2 80 23  6b 87 b5 3b  ed 58 39 66
23 02 b1 64  b6 28 6a 48  cd 1e 09 71  38 e3 cb 90
9b 8b 2b 82  9d d1 8d 2a  35 ff 82 d9  95 34 9e 85
5b f0 2c 29  8e f7 75 f2  d1 a7 e8 b8
      </artwork>
    </figure>
  </section>

  </back>

</rfc>
