diff --git a/handshake/server_config_client.go b/handshake/server_config_client.go index 174328c8..8a589562 100644 --- a/handshake/server_config_client.go +++ b/handshake/server_config_client.go @@ -6,6 +6,7 @@ import ( "errors" "time" + "github.com/lucas-clemente/quic-go/crypto" "github.com/lucas-clemente/quic-go/qerr" ) @@ -14,6 +15,9 @@ type serverConfigClient struct { ID []byte obit []byte expiry time.Time + + kex crypto.KeyExchange + sharedSecret []byte } var ( @@ -93,6 +97,18 @@ func (s *serverConfigClient) parseValues(tagMap map[Tag][]byte) error { return qerr.Error(qerr.CryptoInvalidValueLength, "PUBS") } + var err error + s.kex, err = crypto.NewCurve25519KEX() + if err != nil { + return err + } + + // the PUBS value is always prepended by []byte{0x20, 0x00, 0x00} + s.sharedSecret, err = s.kex.CalculateSharedKey(pubs[3:]) + if err != nil { + return err + } + // OBIT obit, ok := tagMap[TagOBIT] if !ok { diff --git a/handshake/server_config_client_test.go b/handshake/server_config_client_test.go index 967f0676..bfae57cf 100644 --- a/handshake/server_config_client_test.go +++ b/handshake/server_config_client_test.go @@ -4,6 +4,7 @@ import ( "bytes" "time" + "github.com/lucas-clemente/quic-go/crypto" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) @@ -153,6 +154,17 @@ var _ = Describe("Server Config", func() { }) Context("PUBS", func() { + It("creates a Curve25519 key exchange", func() { + serverKex, err := crypto.NewCurve25519KEX() + Expect(err).ToNot(HaveOccurred()) + tagMap[TagPUBS] = append([]byte{0x20, 0x00, 0x00}, serverKex.PublicKey()...) + err = scfg.parseValues(tagMap) + Expect(err).ToNot(HaveOccurred()) + sharedSecret, err := serverKex.CalculateSharedKey(scfg.kex.PublicKey()) + Expect(err).ToNot(HaveOccurred()) + Expect(scfg.sharedSecret).To(Equal(sharedSecret)) + }) + It("rejects PUBS values that have the wrong length", func() { tagMap[TagPUBS] = bytes.Repeat([]byte{'F'}, 100) // completely wrong length err := scfg.parseValues(tagMap)