forked from quic-go/quic-go
@@ -15,6 +15,9 @@ import (
|
|||||||
// KeyDerivationFunction is used for key derivation
|
// KeyDerivationFunction is used for key derivation
|
||||||
type KeyDerivationFunction func(forwardSecure bool, sharedSecret, nonces []byte, connID protocol.ConnectionID, chlo []byte, scfg []byte, cert []byte) (crypto.AEAD, error)
|
type KeyDerivationFunction func(forwardSecure bool, sharedSecret, nonces []byte, connID protocol.ConnectionID, chlo []byte, scfg []byte, cert []byte) (crypto.AEAD, error)
|
||||||
|
|
||||||
|
// KeyExchangeFunction is used to make a new KEX
|
||||||
|
type KeyExchangeFunction func() crypto.KeyExchange
|
||||||
|
|
||||||
// The CryptoSetup handles all things crypto for the Session
|
// The CryptoSetup handles all things crypto for the Session
|
||||||
type CryptoSetup struct {
|
type CryptoSetup struct {
|
||||||
connID protocol.ConnectionID
|
connID protocol.ConnectionID
|
||||||
@@ -28,6 +31,7 @@ type CryptoSetup struct {
|
|||||||
receivedSecurePacket bool
|
receivedSecurePacket bool
|
||||||
|
|
||||||
keyDerivation KeyDerivationFunction
|
keyDerivation KeyDerivationFunction
|
||||||
|
keyExchange KeyExchangeFunction
|
||||||
|
|
||||||
cryptoStream utils.Stream
|
cryptoStream utils.Stream
|
||||||
|
|
||||||
@@ -50,6 +54,7 @@ func NewCryptoSetup(connID protocol.ConnectionID, version protocol.VersionNumber
|
|||||||
scfg: scfg,
|
scfg: scfg,
|
||||||
nonce: nonce,
|
nonce: nonce,
|
||||||
keyDerivation: crypto.DeriveKeysChacha20,
|
keyDerivation: crypto.DeriveKeysChacha20,
|
||||||
|
keyExchange: crypto.NewCurve25519KEX,
|
||||||
cryptoStream: cryptoStream,
|
cryptoStream: cryptoStream,
|
||||||
connectionParametersManager: connectionParametersManager,
|
connectionParametersManager: connectionParametersManager,
|
||||||
}
|
}
|
||||||
@@ -181,8 +186,14 @@ func (h *CryptoSetup) handleCHLO(data []byte, cryptoData map[Tag][]byte) ([]byte
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// TODO: Use new curve
|
|
||||||
h.forwardSecureAEAD, err = h.keyDerivation(true, sharedSecret, nonce.Bytes(), h.connID, data, h.scfg.Get(), h.scfg.signer.GetCertUncompressed())
|
// Generate a new curve instance to derive the forward secure key
|
||||||
|
ephermalKex := h.keyExchange()
|
||||||
|
ephermalSharedSecret, err := ephermalKex.CalculateSharedKey(cryptoData[TagPUBS])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
h.forwardSecureAEAD, err = h.keyDerivation(true, ephermalSharedSecret, nonce.Bytes(), h.connID, data, h.scfg.Get(), h.scfg.signer.GetCertUncompressed())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -194,7 +205,7 @@ func (h *CryptoSetup) handleCHLO(data []byte, cryptoData map[Tag][]byte) ([]byte
|
|||||||
|
|
||||||
replyMap := h.connectionParametersManager.GetSHLOMap()
|
replyMap := h.connectionParametersManager.GetSHLOMap()
|
||||||
// add crypto parameters
|
// add crypto parameters
|
||||||
replyMap[TagPUBS] = h.scfg.kex.PublicKey()
|
replyMap[TagPUBS] = ephermalKex.PublicKey()
|
||||||
replyMap[TagSNO] = h.nonce
|
replyMap[TagSNO] = h.nonce
|
||||||
replyMap[TagVER] = protocol.SupportedVersionsAsTags
|
replyMap[TagVER] = protocol.SupportedVersionsAsTags
|
||||||
|
|
||||||
|
|||||||
@@ -11,12 +11,21 @@ import (
|
|||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
)
|
)
|
||||||
|
|
||||||
type mockKEX struct{}
|
type mockKEX struct {
|
||||||
|
ephermal bool
|
||||||
func (*mockKEX) PublicKey() []byte {
|
}
|
||||||
return []byte("pubs-s")
|
|
||||||
|
func (m *mockKEX) PublicKey() []byte {
|
||||||
|
if m.ephermal {
|
||||||
|
return []byte("ephermal pub")
|
||||||
|
}
|
||||||
|
return []byte("initial public")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockKEX) CalculateSharedKey(otherPublic []byte) ([]byte, error) {
|
||||||
|
if m.ephermal {
|
||||||
|
return []byte("shared ephermal"), nil
|
||||||
}
|
}
|
||||||
func (*mockKEX) CalculateSharedKey(otherPublic []byte) ([]byte, error) {
|
|
||||||
return []byte("shared key"), nil
|
return []byte("shared key"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,6 +48,7 @@ func (*mockSigner) GetCertUncompressed() []byte {
|
|||||||
|
|
||||||
type mockAEAD struct {
|
type mockAEAD struct {
|
||||||
forwardSecure bool
|
forwardSecure bool
|
||||||
|
sharedSecret []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockAEAD) Seal(packetNumber protocol.PacketNumber, associatedData []byte, plaintext []byte) []byte {
|
func (m *mockAEAD) Seal(packetNumber protocol.PacketNumber, associatedData []byte, plaintext []byte) []byte {
|
||||||
@@ -58,7 +68,7 @@ func (m *mockAEAD) Open(packetNumber protocol.PacketNumber, associatedData []byt
|
|||||||
}
|
}
|
||||||
|
|
||||||
func mockKeyDerivation(forwardSecure bool, sharedSecret, nonces []byte, connID protocol.ConnectionID, chlo []byte, scfg []byte, cert []byte) (crypto.AEAD, error) {
|
func mockKeyDerivation(forwardSecure bool, sharedSecret, nonces []byte, connID protocol.ConnectionID, chlo []byte, scfg []byte, cert []byte) (crypto.AEAD, error) {
|
||||||
return &mockAEAD{forwardSecure: forwardSecure}, nil
|
return &mockAEAD{forwardSecure: forwardSecure, sharedSecret: sharedSecret}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type mockStream struct {
|
type mockStream struct {
|
||||||
@@ -101,6 +111,7 @@ var _ = Describe("Crypto setup", func() {
|
|||||||
cpm = NewConnectionParamatersManager()
|
cpm = NewConnectionParamatersManager()
|
||||||
cs = NewCryptoSetup(protocol.ConnectionID(42), v, scfg, stream, cpm)
|
cs = NewCryptoSetup(protocol.ConnectionID(42), v, scfg, stream, cpm)
|
||||||
cs.keyDerivation = mockKeyDerivation
|
cs.keyDerivation = mockKeyDerivation
|
||||||
|
cs.keyExchange = func() crypto.KeyExchange { return &mockKEX{ephermal: true} }
|
||||||
})
|
})
|
||||||
|
|
||||||
It("has a nonce", func() {
|
It("has a nonce", func() {
|
||||||
@@ -118,7 +129,7 @@ var _ = Describe("Crypto setup", func() {
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(response).To(HavePrefix("REJ"))
|
Expect(response).To(HavePrefix("REJ"))
|
||||||
Expect(response).To(ContainSubstring("certcompressed"))
|
Expect(response).To(ContainSubstring("certcompressed"))
|
||||||
Expect(response).To(ContainSubstring("pubs-s"))
|
Expect(response).To(ContainSubstring("initial public"))
|
||||||
Expect(signer.gotCHLO).To(BeTrue())
|
Expect(signer.gotCHLO).To(BeTrue())
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -128,11 +139,15 @@ var _ = Describe("Crypto setup", func() {
|
|||||||
})
|
})
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(response).To(HavePrefix("SHLO"))
|
Expect(response).To(HavePrefix("SHLO"))
|
||||||
Expect(response).To(ContainSubstring("pubs-s")) // TODO: Should be new pubs
|
Expect(response).To(ContainSubstring("ephermal pub"))
|
||||||
Expect(response).To(ContainSubstring(string(cs.nonce)))
|
Expect(response).To(ContainSubstring(string(cs.nonce)))
|
||||||
Expect(response).To(ContainSubstring(string(protocol.SupportedVersionsAsTags)))
|
Expect(response).To(ContainSubstring(string(protocol.SupportedVersionsAsTags)))
|
||||||
Expect(cs.secureAEAD).ToNot(BeNil())
|
Expect(cs.secureAEAD).ToNot(BeNil())
|
||||||
|
Expect(cs.secureAEAD.(*mockAEAD).forwardSecure).To(BeFalse())
|
||||||
|
Expect(cs.secureAEAD.(*mockAEAD).sharedSecret).To(Equal([]byte("shared key")))
|
||||||
Expect(cs.forwardSecureAEAD).ToNot(BeNil())
|
Expect(cs.forwardSecureAEAD).ToNot(BeNil())
|
||||||
|
Expect(cs.forwardSecureAEAD.(*mockAEAD).sharedSecret).To(Equal([]byte("shared ephermal")))
|
||||||
|
Expect(cs.forwardSecureAEAD.(*mockAEAD).forwardSecure).To(BeTrue())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("handles long handshake", func() {
|
It("handles long handshake", func() {
|
||||||
|
|||||||
Reference in New Issue
Block a user