crypto/tls: buffer handshake messages.

This change causes TLS handshake messages to be buffered and written in
a single Write to the underlying net.Conn.

There are two reasons to want to do this:

Firstly, it's slightly preferable to do this in order to save sending
several, small packets over the network where a single one will do.

Secondly, since 37c28759ca errors from
Write have been returned from a handshake. This means that, if a peer
closes the connection during a handshake, a “broken pipe” error may
result from tls.Conn.Handshake(). This can mask any, more detailed,
fatal alerts that the peer may have sent because a read will never
happen.

Buffering handshake messages means that the peer will not receive, and
possibly reject, any of a flow while it's still being written.

Fixes #15709

Change-Id: I38dcff1abecc06e52b2de647ea98713ce0fb9a21
Reviewed-on: https://go-review.googlesource.com/23609
Reviewed-by: Andrew Gerrand <adg@golang.org>
Run-TryBot: Andrew Gerrand <adg@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Adam Langley 2016-06-01 14:41:09 -07:00 committed by Andrew Gerrand
parent f6c0241999
commit 2a8c81ffaa
4 changed files with 93 additions and 7 deletions

View file

@ -206,6 +206,7 @@ NextCipherSuite:
hs.finishedHash.Write(hs.hello.marshal())
hs.finishedHash.Write(hs.serverHello.marshal())
c.buffering = true
if isResume {
if err := hs.establishKeys(); err != nil {
return err
@ -220,6 +221,9 @@ NextCipherSuite:
if err := hs.sendFinished(c.clientFinished[:]); err != nil {
return err
}
if _, err := c.flush(); err != nil {
return err
}
} else {
if err := hs.doFullHandshake(); err != nil {
return err
@ -230,6 +234,9 @@ NextCipherSuite:
if err := hs.sendFinished(c.clientFinished[:]); err != nil {
return err
}
if _, err := c.flush(); err != nil {
return err
}
c.clientFinishedIsFirst = true
if err := hs.readSessionTicket(); err != nil {
return err