From c5f88e01f5a4ede78036f826a29975e6970463d7 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Thu, 10 Nov 2016 22:05:40 +0700 Subject: [PATCH] implement a CertManager for the certificate chain sent by the server --- crypto/cert_manager.go | 34 +++++++++++++++++++++++++++ crypto/cert_manager_test.go | 46 +++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 crypto/cert_manager.go create mode 100644 crypto/cert_manager_test.go diff --git a/crypto/cert_manager.go b/crypto/cert_manager.go new file mode 100644 index 000000000..671c29859 --- /dev/null +++ b/crypto/cert_manager.go @@ -0,0 +1,34 @@ +package crypto + +import ( + "errors" + + "github.com/lucas-clemente/quic-go/qerr" +) + +// CertManager manages the certificates sent by the server +type CertManager struct { + chain [][]byte +} + +var errNoCertificateChain = errors.New("No certicifate chain loaded") + +// SetData takes the byte-slice sent in the SHLO and decompresses it into the certificate chain +func (c *CertManager) SetData(data []byte) error { + chain, err := decompressChain(data) + if err != nil { + return qerr.ProofInvalid + } + c.chain = chain + + return nil +} + +// GetLeafCert returns the leaf certificate of the certificate chain +// it errors if the certificate chain has not yet been set +func (c *CertManager) GetLeafCert() []byte { + if len(c.chain) == 0 { + return nil + } + return c.chain[0] +} diff --git a/crypto/cert_manager_test.go b/crypto/cert_manager_test.go new file mode 100644 index 000000000..77192c6f5 --- /dev/null +++ b/crypto/cert_manager_test.go @@ -0,0 +1,46 @@ +package crypto + +import ( + "github.com/lucas-clemente/quic-go/qerr" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Cert Manager", func() { + var cm *CertManager + + BeforeEach(func() { + cm = &CertManager{} + }) + + It("errors when given invalid data", func() { + err := cm.SetData([]byte("foobar")) + Expect(err).To(MatchError(qerr.ProofInvalid)) + }) + + It("decompresses a certificate chain", func() { + cert1 := []byte{0xde, 0xca, 0xfb, 0xad} + cert2 := []byte{0xde, 0xad, 0xbe, 0xef, 0x13, 0x37} + chain := [][]byte{cert1, cert2} + compressed, err := compressChain(chain, nil, nil) + Expect(err).ToNot(HaveOccurred()) + err = cm.SetData(compressed) + Expect(err).ToNot(HaveOccurred()) + Expect(cm.chain).To(Equal(chain)) + }) + + Context("getting the leaf cert", func() { + It("gets it", func() { + cert1 := []byte{0xc1} + cert2 := []byte{0xc2} + cm.chain = [][]byte{cert1, cert2} + leafCert := cm.GetLeafCert() + Expect(leafCert).To(Equal(cert1)) + }) + + It("returns nil if the chain hasn't been set yet", func() { + leafCert := cm.GetLeafCert() + Expect(leafCert).To(BeNil()) + }) + }) +})