generate a client nonce after receiving a server config

This commit is contained in:
Marten Seemann
2016-11-11 00:30:31 +07:00
parent 39e7591756
commit f1810ae82d
2 changed files with 49 additions and 17 deletions

View File

@@ -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
}

View File

@@ -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))
})
})