@@ -16,6 +16,7 @@ import (
1616 "hash"
1717 "io"
1818 "io/ioutil"
19+ "math/bits"
1920
2021 "golang.org/x/crypto/internal/chacha20"
2122 "golang.org/x/crypto/poly1305"
641642// the methods here also implement padding, which RFC4253 Section 6
642643// also requires of stream ciphers.
643644type chacha20Poly1305Cipher struct {
644- lengthKey [32 ] byte
645- contentKey [32 ] byte
645+ lengthKey [8 ] uint32
646+ contentKey [8 ] uint32
646647 buf []byte
647648}
648649
@@ -655,28 +656,29 @@ func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs directionA
655656 buf : make ([]byte , 256 ),
656657 }
657658
658- copy (c .contentKey [:], key [:32 ])
659- copy (c .lengthKey [:], key [32 :])
659+ for i := range c .contentKey {
660+ c .contentKey [i ] = binary .LittleEndian .Uint32 (key [i * 4 : (i + 1 )* 4 ])
661+ }
662+ for i := range c .contentKey {
663+ c .lengthKey [i ] = binary .LittleEndian .Uint32 (key [(i + 8 )* 4 : (i + 9 )* 4 ])
664+ }
660665 return c , nil
661666}
662667
663- // The Poly1305 key is obtained by encrypting 32 0-bytes.
664- var chacha20PolyKeyInput [32 ]byte
665-
666668func (c * chacha20Poly1305Cipher ) readPacket (seqNum uint32 , r io.Reader ) ([]byte , error ) {
667- var counter [16 ]byte
668- binary .BigEndian .PutUint64 (counter [8 :], uint64 (seqNum ))
669-
669+ nonce := [3 ]uint32 {0 , 0 , bits .ReverseBytes32 (seqNum )}
670+ s := chacha20 .New (c .contentKey , nonce )
670671 var polyKey [32 ]byte
671- chacha20 .XORKeyStream (polyKey [:], chacha20PolyKeyInput [:], & counter , & c .contentKey )
672+ s .XORKeyStream (polyKey [:], polyKey [:])
673+ s .Advance () // skip next 32 bytes
672674
673675 encryptedLength := c .buf [:4 ]
674676 if _ , err := io .ReadFull (r , encryptedLength ); err != nil {
675677 return nil , err
676678 }
677679
678680 var lenBytes [4 ]byte
679- chacha20 .XORKeyStream (lenBytes [:], encryptedLength , & counter , & c . lengthKey )
681+ chacha20 .New ( c . lengthKey , nonce ). XORKeyStream (lenBytes [:], encryptedLength )
680682
681683 length := binary .BigEndian .Uint32 (lenBytes [:])
682684 if length > maxPacket {
@@ -702,10 +704,8 @@ func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte,
702704 return nil , errors .New ("ssh: MAC failure" )
703705 }
704706
705- counter [0 ] = 1
706-
707707 plain := c .buf [4 :contentEnd ]
708- chacha20 .XORKeyStream (plain , plain , & counter , & c . contentKey )
708+ s .XORKeyStream (plain , plain )
709709
710710 padding := plain [0 ]
711711 if padding < 4 {
@@ -724,11 +724,11 @@ func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte,
724724}
725725
726726func (c * chacha20Poly1305Cipher ) writePacket (seqNum uint32 , w io.Writer , rand io.Reader , payload []byte ) error {
727- var counter [16 ]byte
728- binary .BigEndian .PutUint64 (counter [8 :], uint64 (seqNum ))
729-
727+ nonce := [3 ]uint32 {0 , 0 , bits .ReverseBytes32 (seqNum )}
728+ s := chacha20 .New (c .contentKey , nonce )
730729 var polyKey [32 ]byte
731- chacha20 .XORKeyStream (polyKey [:], chacha20PolyKeyInput [:], & counter , & c .contentKey )
730+ s .XORKeyStream (polyKey [:], polyKey [:])
731+ s .Advance () // skip next 32 bytes
732732
733733 // There is no blocksize, so fall back to multiple of 8 byte
734734 // padding, as described in RFC 4253, Sec 6.
@@ -748,16 +748,15 @@ func (c *chacha20Poly1305Cipher) writePacket(seqNum uint32, w io.Writer, rand io
748748 }
749749
750750 binary .BigEndian .PutUint32 (c .buf , uint32 (1 + len (payload )+ padding ))
751- chacha20 .XORKeyStream (c .buf , c .buf [:4 ], & counter , & c . lengthKey )
751+ chacha20 .New ( c . lengthKey , nonce ). XORKeyStream (c .buf , c .buf [:4 ])
752752 c .buf [4 ] = byte (padding )
753753 copy (c .buf [5 :], payload )
754754 packetEnd := 5 + len (payload ) + padding
755755 if _ , err := io .ReadFull (rand , c .buf [5 + len (payload ):packetEnd ]); err != nil {
756756 return err
757757 }
758758
759- counter [0 ] = 1
760- chacha20 .XORKeyStream (c .buf [4 :], c .buf [4 :packetEnd ], & counter , & c .contentKey )
759+ s .XORKeyStream (c .buf [4 :], c .buf [4 :packetEnd ])
761760
762761 var mac [poly1305 .TagSize ]byte
763762 poly1305 .Sum (& mac , c .buf [:packetEnd ], & polyKey )
0 commit comments