forked from quic-go/quic-go
generate a client nonce after receiving a server config
This commit is contained in:
@@ -24,6 +24,7 @@ type cryptoSetupClient struct {
|
||||
|
||||
stk []byte
|
||||
sno []byte
|
||||
nonc []byte
|
||||
diversificationNonce []byte
|
||||
certManager *crypto.CertManager
|
||||
}
|
||||
@@ -32,7 +33,8 @@ var _ crypto.AEAD = &cryptoSetupClient{}
|
||||
var _ CryptoSetup = &cryptoSetupClient{}
|
||||
|
||||
var (
|
||||
errNoObitForClientNonce = errors.New("No OBIT for client nonce available")
|
||||
errNoObitForClientNonce = errors.New("CryptoSetup BUG: No OBIT for client nonce available")
|
||||
errClientNonceAlreadyExists = errors.New("CryptoSetup BUG: A client nonce was already generated")
|
||||
errConflictingDiversificationNonces = errors.New("Received two different diversification nonces")
|
||||
)
|
||||
|
||||
@@ -100,6 +102,12 @@ func (h *cryptoSetupClient) handleREJMessage(cryptoData map[Tag][]byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// now that we have a server config, we can use its OBIT value to generate a client nonce
|
||||
err = h.generateClientNonce()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if crt, ok := cryptoData[TagCERT]; ok {
|
||||
@@ -185,20 +193,25 @@ func (h *cryptoSetupClient) getTags() map[Tag][]byte {
|
||||
return tags
|
||||
}
|
||||
|
||||
func (h *cryptoSetupClient) generateClientNonce() ([]byte, error) {
|
||||
nonce := make([]byte, 32)
|
||||
binary.BigEndian.PutUint32(nonce, uint32(time.Now().Unix()))
|
||||
func (h *cryptoSetupClient) generateClientNonce() error {
|
||||
if len(h.nonc) > 0 {
|
||||
return errClientNonceAlreadyExists
|
||||
}
|
||||
|
||||
nonc := make([]byte, 32)
|
||||
binary.BigEndian.PutUint32(nonc, uint32(time.Now().Unix()))
|
||||
|
||||
if len(h.serverConfig.obit) != 8 {
|
||||
return nil, errNoObitForClientNonce
|
||||
return errNoObitForClientNonce
|
||||
}
|
||||
|
||||
copy(nonce[4:12], h.serverConfig.obit)
|
||||
copy(nonc[4:12], h.serverConfig.obit)
|
||||
|
||||
_, err := rand.Read(nonce[12:])
|
||||
_, err := rand.Read(nonc[12:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
return nonce, nil
|
||||
h.nonc = nonc
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ var _ = Describe("Crypto setup", func() {
|
||||
Expect(err).To(MatchError(qerr.InvalidCryptoMessageType))
|
||||
})
|
||||
|
||||
It("errors on invalid hanshake messages", func() {
|
||||
It("errors on invalid handshake messages", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteHandshakeMessage(b, TagCHLO, tagMap)
|
||||
stream.dataToRead.Write(b.Bytes()[:b.Len()-2]) // cut the handshake message
|
||||
@@ -81,6 +81,15 @@ var _ = Describe("Crypto setup", func() {
|
||||
Expect(cs.serverConfig.ID).To(Equal(scfg[TagSCID]))
|
||||
})
|
||||
|
||||
It("generates a client nonce after reading a server config", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteHandshakeMessage(b, TagSCFG, getDefaultServerConfigClient())
|
||||
tagMap[TagSCFG] = b.Bytes()
|
||||
err := cs.handleREJMessage(tagMap)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(cs.nonc).To(HaveLen(32))
|
||||
})
|
||||
|
||||
It("passes on errors from reading the server config", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteHandshakeMessage(b, TagSHLO, make(map[Tag][]byte))
|
||||
@@ -169,25 +178,35 @@ var _ = Describe("Crypto setup", func() {
|
||||
|
||||
It("generates a client nonce", func() {
|
||||
now := time.Now()
|
||||
nonce, err := cs.generateClientNonce()
|
||||
Expect(nonce).To(HaveLen(32))
|
||||
err := cs.generateClientNonce()
|
||||
Expect(cs.nonc).To(HaveLen(32))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(time.Unix(int64(binary.BigEndian.Uint32(nonce[0:4])), 0)).To(BeTemporally("~", now, 1*time.Second))
|
||||
Expect(nonce[4:12]).To(Equal(cs.serverConfig.obit))
|
||||
Expect(time.Unix(int64(binary.BigEndian.Uint32(cs.nonc[0:4])), 0)).To(BeTemporally("~", now, 1*time.Second))
|
||||
Expect(cs.nonc[4:12]).To(Equal(cs.serverConfig.obit))
|
||||
})
|
||||
|
||||
It("uses random values for the last 20 bytes", func() {
|
||||
nonce1, err := cs.generateClientNonce()
|
||||
err := cs.generateClientNonce()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
nonce2, err := cs.generateClientNonce()
|
||||
nonce1 := cs.nonc
|
||||
cs.nonc = []byte{}
|
||||
err = cs.generateClientNonce()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
nonce2 := cs.nonc
|
||||
Expect(nonce1[4:12]).To(Equal(nonce2[4:12]))
|
||||
Expect(nonce1[12:]).ToNot(Equal(nonce2[12:]))
|
||||
})
|
||||
|
||||
It("errors if a client nonce has already been generated", func() {
|
||||
err := cs.generateClientNonce()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = cs.generateClientNonce()
|
||||
Expect(err).To(MatchError(errClientNonceAlreadyExists))
|
||||
})
|
||||
|
||||
It("errors if no OBIT value is available", func() {
|
||||
cs.serverConfig.obit = []byte{}
|
||||
_, err := cs.generateClientNonce()
|
||||
err := cs.generateClientNonce()
|
||||
Expect(err).To(MatchError(errNoObitForClientNonce))
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user