forked from quic-go/quic-go
fix a race condition in CryptoSetup
CryptoSetup's AEADs were changed between calls to DiversificationNonce() and Seal()
This commit is contained in:
@@ -169,11 +169,8 @@ func (h *CryptoSetup) Open(packetNumber protocol.PacketNumber, associatedData []
|
|||||||
return (&crypto.NullAEAD{}).Open(packetNumber, associatedData, ciphertext)
|
return (&crypto.NullAEAD{}).Open(packetNumber, associatedData, ciphertext)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seal a message
|
// Seal a message, call LockForSealing() before!
|
||||||
func (h *CryptoSetup) Seal(packetNumber protocol.PacketNumber, associatedData []byte, plaintext []byte) []byte {
|
func (h *CryptoSetup) Seal(packetNumber protocol.PacketNumber, associatedData []byte, plaintext []byte) []byte {
|
||||||
h.mutex.RLock()
|
|
||||||
defer h.mutex.RUnlock()
|
|
||||||
|
|
||||||
if h.receivedForwardSecurePacket {
|
if h.receivedForwardSecurePacket {
|
||||||
return h.forwardSecureAEAD.Seal(packetNumber, associatedData, plaintext)
|
return h.forwardSecureAEAD.Seal(packetNumber, associatedData, plaintext)
|
||||||
} else if h.secureAEAD != nil {
|
} else if h.secureAEAD != nil {
|
||||||
@@ -308,7 +305,7 @@ func (h *CryptoSetup) handleCHLO(sni string, data []byte, cryptoData map[Tag][]b
|
|||||||
return reply.Bytes(), nil
|
return reply.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiversificationNonce returns a diversification nonce if required in the next packet to be Seal'ed
|
// DiversificationNonce returns a diversification nonce if required in the next packet to be Seal'ed. See LockForSealing()!
|
||||||
func (h *CryptoSetup) DiversificationNonce() []byte {
|
func (h *CryptoSetup) DiversificationNonce() []byte {
|
||||||
if h.version < protocol.VersionNumber(33) {
|
if h.version < protocol.VersionNumber(33) {
|
||||||
return nil
|
return nil
|
||||||
@@ -319,6 +316,16 @@ func (h *CryptoSetup) DiversificationNonce() []byte {
|
|||||||
return h.diversificationNonce
|
return h.diversificationNonce
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LockForSealing should be called before Seal(). It is needed so that diversification nonces can be obtained before packets are sealed, and the AEADs are not changed in the meantime.
|
||||||
|
func (h *CryptoSetup) LockForSealing() {
|
||||||
|
h.mutex.RLock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnlockForSealing should be called after Seal() is complete, see LockForSealing().
|
||||||
|
func (h *CryptoSetup) UnlockForSealing() {
|
||||||
|
h.mutex.RUnlock()
|
||||||
|
}
|
||||||
|
|
||||||
func (h *CryptoSetup) verifyOrCreateSTK(token []byte) ([]byte, error) {
|
func (h *CryptoSetup) verifyOrCreateSTK(token []byte) ([]byte, error) {
|
||||||
err := h.scfg.stkSource.VerifyToken(h.ip, token)
|
err := h.scfg.stkSource.VerifyToken(h.ip, token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go/ackhandler"
|
"github.com/lucas-clemente/quic-go/ackhandler"
|
||||||
"github.com/lucas-clemente/quic-go/crypto"
|
|
||||||
"github.com/lucas-clemente/quic-go/frames"
|
"github.com/lucas-clemente/quic-go/frames"
|
||||||
"github.com/lucas-clemente/quic-go/handshake"
|
"github.com/lucas-clemente/quic-go/handshake"
|
||||||
"github.com/lucas-clemente/quic-go/protocol"
|
"github.com/lucas-clemente/quic-go/protocol"
|
||||||
@@ -23,7 +22,7 @@ type packedPacket struct {
|
|||||||
type packetPacker struct {
|
type packetPacker struct {
|
||||||
connectionID protocol.ConnectionID
|
connectionID protocol.ConnectionID
|
||||||
version protocol.VersionNumber
|
version protocol.VersionNumber
|
||||||
aead crypto.AEAD
|
cryptoSetup *handshake.CryptoSetup
|
||||||
|
|
||||||
sentPacketHandler ackhandler.SentPacketHandler
|
sentPacketHandler ackhandler.SentPacketHandler
|
||||||
connectionParametersManager *handshake.ConnectionParametersManager
|
connectionParametersManager *handshake.ConnectionParametersManager
|
||||||
@@ -35,9 +34,9 @@ type packetPacker struct {
|
|||||||
lastPacketNumber protocol.PacketNumber
|
lastPacketNumber protocol.PacketNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPacketPacker(connectionID protocol.ConnectionID, aead crypto.AEAD, sentPacketHandler ackhandler.SentPacketHandler, connectionParametersHandler *handshake.ConnectionParametersManager, blockedManager *blockedManager, version protocol.VersionNumber) *packetPacker {
|
func newPacketPacker(connectionID protocol.ConnectionID, cryptoSetup *handshake.CryptoSetup, sentPacketHandler ackhandler.SentPacketHandler, connectionParametersHandler *handshake.ConnectionParametersManager, blockedManager *blockedManager, version protocol.VersionNumber) *packetPacker {
|
||||||
return &packetPacker{
|
return &packetPacker{
|
||||||
aead: aead,
|
cryptoSetup: cryptoSetup,
|
||||||
connectionID: connectionID,
|
connectionID: connectionID,
|
||||||
connectionParametersManager: connectionParametersHandler,
|
connectionParametersManager: connectionParametersHandler,
|
||||||
version: version,
|
version: version,
|
||||||
@@ -89,13 +88,18 @@ func (p *packetPacker) packPacket(stopWaitingFrame *frames.StopWaitingFrame, con
|
|||||||
1,
|
1,
|
||||||
))
|
))
|
||||||
|
|
||||||
|
// cryptoSetup needs to be locked here, so that the AEADs are not changed between
|
||||||
|
// calling DiversificationNonce() and Seal().
|
||||||
|
p.cryptoSetup.LockForSealing()
|
||||||
|
defer p.cryptoSetup.UnlockForSealing()
|
||||||
|
|
||||||
packetNumberLen := protocol.GetPacketNumberLengthForPublicHeader(currentPacketNumber, p.sentPacketHandler.GetLargestObserved())
|
packetNumberLen := protocol.GetPacketNumberLengthForPublicHeader(currentPacketNumber, p.sentPacketHandler.GetLargestObserved())
|
||||||
responsePublicHeader := &publicHeader{
|
responsePublicHeader := &publicHeader{
|
||||||
ConnectionID: p.connectionID,
|
ConnectionID: p.connectionID,
|
||||||
PacketNumber: currentPacketNumber,
|
PacketNumber: currentPacketNumber,
|
||||||
PacketNumberLen: packetNumberLen,
|
PacketNumberLen: packetNumberLen,
|
||||||
TruncateConnectionID: p.connectionParametersManager.TruncateConnectionID(),
|
TruncateConnectionID: p.connectionParametersManager.TruncateConnectionID(),
|
||||||
DiversificationNonce: p.aead.DiversificationNonce(),
|
DiversificationNonce: p.cryptoSetup.DiversificationNonce(),
|
||||||
}
|
}
|
||||||
|
|
||||||
publicHeaderLength, err := responsePublicHeader.GetLength()
|
publicHeaderLength, err := responsePublicHeader.GetLength()
|
||||||
@@ -136,7 +140,7 @@ func (p *packetPacker) packPacket(stopWaitingFrame *frames.StopWaitingFrame, con
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ciphertext := p.aead.Seal(currentPacketNumber, raw.Bytes(), payload)
|
ciphertext := p.cryptoSetup.Seal(currentPacketNumber, raw.Bytes(), payload)
|
||||||
raw.Write(ciphertext)
|
raw.Write(ciphertext)
|
||||||
|
|
||||||
if protocol.ByteCount(raw.Len()) > protocol.MaxPacketSize {
|
if protocol.ByteCount(raw.Len()) > protocol.MaxPacketSize {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go/ackhandler"
|
"github.com/lucas-clemente/quic-go/ackhandler"
|
||||||
"github.com/lucas-clemente/quic-go/crypto"
|
|
||||||
"github.com/lucas-clemente/quic-go/frames"
|
"github.com/lucas-clemente/quic-go/frames"
|
||||||
"github.com/lucas-clemente/quic-go/handshake"
|
"github.com/lucas-clemente/quic-go/handshake"
|
||||||
"github.com/lucas-clemente/quic-go/protocol"
|
"github.com/lucas-clemente/quic-go/protocol"
|
||||||
@@ -36,9 +35,8 @@ var _ = Describe("Packet packer", func() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
aead := &crypto.NullAEAD{}
|
|
||||||
packer = &packetPacker{
|
packer = &packetPacker{
|
||||||
aead: aead,
|
cryptoSetup: &handshake.CryptoSetup{},
|
||||||
connectionParametersManager: handshake.NewConnectionParamatersManager(),
|
connectionParametersManager: handshake.NewConnectionParamatersManager(),
|
||||||
sentPacketHandler: newMockSentPacketHandler(),
|
sentPacketHandler: newMockSentPacketHandler(),
|
||||||
blockedManager: newBlockedManager(),
|
blockedManager: newBlockedManager(),
|
||||||
|
|||||||
Reference in New Issue
Block a user