verify OBIT value in client nonce

fixes #350
This commit is contained in:
Marten Seemann
2016-11-28 19:26:46 +07:00
parent bbbc24c431
commit 6602101288
3 changed files with 33 additions and 6 deletions

View File

@@ -248,8 +248,9 @@ func (h *CryptoSetup) handleCHLO(sni string, data []byte, cryptoData map[Tag][]b
}
clientNonce := cryptoData[TagNONC]
if len(clientNonce) != 32 {
return nil, qerr.Error(qerr.InvalidCryptoMessageParameter, "invalid client nonce length")
err = h.validateClientNonce(clientNonce)
if err != nil {
return nil, err
}
h.secureAEAD, err = h.keyDerivation(
@@ -331,3 +332,13 @@ func (h *CryptoSetup) UnlockForSealing() {
func (h *CryptoSetup) HandshakeComplete() bool {
return h.receivedForwardSecurePacket
}
func (h *CryptoSetup) validateClientNonce(nonce []byte) error {
if len(nonce) != 32 {
return qerr.Error(qerr.InvalidCryptoMessageParameter, "invalid client nonce length")
}
if !bytes.Equal(nonce[4:12], h.scfg.obit) {
return qerr.Error(qerr.InvalidCryptoMessageParameter, "OBIT not matching")
}
return nil
}

View File

@@ -150,7 +150,6 @@ var _ = Describe("Crypto setup", func() {
ip = net.ParseIP("1.2.3.4")
validSTK, err = mockStkSource{}.NewToken(ip)
Expect(err).NotTo(HaveOccurred())
nonce32 = make([]byte, 32)
expectedInitialNonceLen = 32
expectedFSNonceLen = 64
aeadChanged = make(chan struct{}, 1)
@@ -158,6 +157,8 @@ var _ = Describe("Crypto setup", func() {
kex = &mockKEX{}
signer = &mockSigner{}
scfg, err = NewServerConfig(kex, signer)
nonce32 = make([]byte, 32)
copy(nonce32[4:12], scfg.obit) // set the OBIT value at the right position
Expect(err).NotTo(HaveOccurred())
scfg.stkSource = &mockStkSource{}
v := protocol.SupportedVersions[len(protocol.SupportedVersions)-1]
@@ -274,6 +275,19 @@ var _ = Describe("Crypto setup", func() {
Expect(err).To(MatchError(qerr.Error(qerr.InvalidCryptoMessageParameter, "invalid client nonce length")))
})
It("rejects client nonces that have the wrong OBIT value", func() {
nonce := make([]byte, 32) // the OBIT value is nonce[4:12] and here just initialized to 0
WriteHandshakeMessage(&stream.dataToRead, TagCHLO, map[Tag][]byte{
TagSCID: scfg.ID,
TagSNI: []byte("quic.clemente.io"),
TagNONC: nonce,
TagSTK: validSTK,
TagPUBS: nil,
})
err := cs.HandleCryptoStream()
Expect(err).To(MatchError(qerr.Error(qerr.InvalidCryptoMessageParameter, "OBIT not matching")))
})
It("handles 0-RTT handshake", func() {
WriteHandshakeMessage(&stream.dataToRead, TagCHLO, map[Tag][]byte{
TagSCID: scfg.ID,

View File

@@ -9,9 +9,10 @@ import (
// ServerConfig is a server config
type ServerConfig struct {
ID []byte
obit []byte
kex crypto.KeyExchange
signer crypto.Signer
ID []byte
stkSource crypto.StkSource
}
@@ -33,9 +34,10 @@ func NewServerConfig(kex crypto.KeyExchange, signer crypto.Signer) (*ServerConfi
}
return &ServerConfig{
ID: id,
obit: []byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7},
kex: kex,
signer: signer,
ID: id,
stkSource: stkSource,
}, nil
}
@@ -48,7 +50,7 @@ func (s *ServerConfig) Get() []byte {
TagKEXS: []byte("C255"),
TagAEAD: []byte("AESG"),
TagPUBS: append([]byte{0x20, 0x00, 0x00}, s.kex.PublicKey()...),
TagOBIT: {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7},
TagOBIT: s.obit,
TagEXPY: {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
})
return serverConfig.Bytes()