move handshake handling and server config into handshake package

This commit is contained in:
Lucas Clemente
2016-04-15 22:24:42 +02:00
parent 30d5766598
commit 20b48c5432
6 changed files with 123 additions and 77 deletions

80
handshake/handshake.go Normal file
View File

@@ -0,0 +1,80 @@
package handshake
import (
"bytes"
"errors"
"io"
"github.com/lucas-clemente/quic-go/crypto"
"github.com/lucas-clemente/quic-go/protocol"
)
// The Handshake handles all things crypto for the Session
type Handshake struct {
connID protocol.ConnectionID
version protocol.VersionNumber
aead crypto.AEAD
scfg *ServerConfig
}
// NewHandshake creates a new Handshake instance
func NewHandshake(connID protocol.ConnectionID, version protocol.VersionNumber, scfg *ServerConfig) *Handshake {
return &Handshake{
connID: connID,
version: version,
aead: &crypto.NullAEAD{},
scfg: scfg,
}
}
// Open a message
func (h *Handshake) Open(packetNumber protocol.PacketNumber, associatedData []byte, ciphertext io.Reader) (*bytes.Reader, error) {
return h.aead.Open(packetNumber, associatedData, ciphertext)
}
// Seal a messageTag
func (h *Handshake) Seal(packetNumber protocol.PacketNumber, b *bytes.Buffer, associatedData []byte, plaintext []byte) {
h.aead.Seal(packetNumber, b, associatedData, plaintext)
}
// HandleCryptoMessage handles the crypto handshake and returns the answer
func (h *Handshake) HandleCryptoMessage(data []byte) ([]byte, error) {
messageTag, cryptoData, err := ParseHandshakeMessage(data)
if err != nil {
return nil, err
}
if messageTag != TagCHLO {
return nil, errors.New("Session: expected CHLO")
}
if _, ok := cryptoData[TagSCID]; ok {
var sharedSecret []byte
sharedSecret, err = h.scfg.kex.CalculateSharedKey(cryptoData[TagPUBS])
if err != nil {
return nil, err
}
h.aead, err = crypto.DeriveKeysChacha20(sharedSecret, cryptoData[TagNONC], h.connID, data, h.scfg.Get(), h.scfg.kd.GetCertUncompressed())
if err != nil {
return nil, err
}
// TODO: Send SHLO
return nil, nil
}
var chloOrNil []byte
if h.version > protocol.VersionNumber(30) {
chloOrNil = data
}
proof, err := h.scfg.Sign(chloOrNil)
if err != nil {
return nil, err
}
var serverReply bytes.Buffer
WriteHandshakeMessage(&serverReply, TagREJ, map[Tag][]byte{
TagSCFG: h.scfg.Get(),
TagCERT: h.scfg.GetCertCompressed(),
TagPROF: proof,
})
return serverReply.Bytes(), nil
}

View File

@@ -0,0 +1,9 @@
package handshake
import (
. "github.com/onsi/ginkgo"
// . "github.com/onsi/gomega"
)
var _ = Describe("Handshake", func() {
})

View File

@@ -0,0 +1,46 @@
package handshake
import (
"bytes"
"github.com/lucas-clemente/quic-go/crypto"
)
// ServerConfig is a server config
type ServerConfig struct {
kex crypto.KeyExchange
kd *crypto.KeyData
}
// NewServerConfig creates a new server config
func NewServerConfig(kex crypto.KeyExchange, kd *crypto.KeyData) *ServerConfig {
return &ServerConfig{
kex: kex,
kd: kd,
}
}
// Get the server config binary representation
func (s *ServerConfig) Get() []byte {
var serverConfig bytes.Buffer
WriteHandshakeMessage(&serverConfig, TagSCFG, map[Tag][]byte{
TagSCID: []byte{0xC5, 0x1C, 0x73, 0x6B, 0x8F, 0x48, 0x49, 0xAE, 0xB3, 0x00, 0xA2, 0xD4, 0x4B, 0xA0, 0xCF, 0xDF},
TagKEXS: []byte("C255"),
TagAEAD: []byte("CC20"),
TagPUBS: append([]byte{0x20, 0x00, 0x00}, s.kex.PublicKey()...),
TagOBIT: []byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7},
TagEXPY: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
TagVER: []byte("Q032"),
})
return serverConfig.Bytes()
}
// Sign the server config and CHLO with the server's keyData
func (s *ServerConfig) Sign(chlo []byte) ([]byte, error) {
return s.kd.SignServerProof(chlo, s.Get())
}
// GetCertCompressed returns the certificate data
func (s *ServerConfig) GetCertCompressed() []byte {
return s.kd.GetCertCompressed()
}

View File

@@ -0,0 +1,29 @@
package handshake
import (
"bytes"
"github.com/lucas-clemente/quic-go/crypto"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("ServerConfig", func() {
var (
kex crypto.KeyExchange
scfg *ServerConfig
)
BeforeEach(func() {
kex = crypto.NewCurve25519KEX()
scfg = NewServerConfig(kex, nil)
})
It("gets the proper binary representation", func() {
expected := bytes.NewBuffer([]byte{0x53, 0x43, 0x46, 0x47, 0x7, 0x0, 0x0, 0x0, 0x56, 0x45, 0x52, 0x0, 0x4, 0x0, 0x0, 0x0, 0x41, 0x45, 0x41, 0x44, 0x8, 0x0, 0x0, 0x0, 0x53, 0x43, 0x49, 0x44, 0x18, 0x0, 0x0, 0x0, 0x50, 0x55, 0x42, 0x53, 0x3b, 0x0, 0x0, 0x0, 0x4b, 0x45, 0x58, 0x53, 0x3f, 0x0, 0x0, 0x0, 0x4f, 0x42, 0x49, 0x54, 0x47, 0x0, 0x0, 0x0, 0x45, 0x58, 0x50, 0x59, 0x4f, 0x0, 0x0, 0x0, 0x51, 0x30, 0x33, 0x32, 0x43, 0x43, 0x32, 0x30, 0xc5, 0x1c, 0x73, 0x6b, 0x8f, 0x48, 0x49, 0xae, 0xb3, 0x0, 0xa2, 0xd4, 0x4b, 0xa0, 0xcf, 0xdf, 0x20, 0x0, 0x0})
expected.Write(kex.PublicKey())
expected.Write([]byte{0x43, 0x32, 0x35, 0x35, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff})
Expect(scfg.Get()).To(Equal(expected.Bytes()))
})
})