forked from quic-go/quic-go
simplify server proof verification function signature
This commit is contained in:
@@ -11,7 +11,7 @@ import (
|
||||
type CertManager interface {
|
||||
SetData([]byte) error
|
||||
GetLeafCert() []byte
|
||||
VerifyServerProof(proof, chlo, serverConfigData []byte) (bool, error)
|
||||
VerifyServerProof(proof, chlo, serverConfigData []byte) bool
|
||||
Verify(hostname string) error
|
||||
}
|
||||
|
||||
@@ -57,12 +57,14 @@ func (c *certManager) GetLeafCert() []byte {
|
||||
return c.chain[0].Raw
|
||||
}
|
||||
|
||||
func (c *certManager) VerifyServerProof(proof, chlo, serverConfigData []byte) (bool, error) {
|
||||
// VerifyServerProof verifies the signature of the server config
|
||||
// it should only be called after the certificate chain has been set, otherwise it returns false
|
||||
func (c *certManager) VerifyServerProof(proof, chlo, serverConfigData []byte) bool {
|
||||
if len(c.chain) == 0 {
|
||||
return false, errNoCertificateChain
|
||||
return false
|
||||
}
|
||||
|
||||
return verifyServerProof(proof, c.chain[0], chlo, serverConfigData), nil
|
||||
return verifyServerProof(proof, c.chain[0], chlo, serverConfigData)
|
||||
}
|
||||
|
||||
// Verify verifies the certificate chain
|
||||
|
||||
@@ -3,6 +3,7 @@ package crypto
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
@@ -19,13 +20,15 @@ import (
|
||||
|
||||
var _ = Describe("Cert Manager", func() {
|
||||
var cm *certManager
|
||||
var key1, key2 *rsa.PrivateKey
|
||||
var cert1, cert2 []byte
|
||||
|
||||
BeforeEach(func() {
|
||||
var err error
|
||||
cm = NewCertManager().(*certManager)
|
||||
key1, err := rsa.GenerateKey(rand.Reader, 512)
|
||||
key1, err = rsa.GenerateKey(rand.Reader, 768)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
key2, err := rsa.GenerateKey(rand.Reader, 512)
|
||||
key2, err = rsa.GenerateKey(rand.Reader, 768)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
template := &x509.Certificate{SerialNumber: big.NewInt(1)}
|
||||
cert1, err = x509.CreateCertificate(rand.Reader, template, template, &key1.PublicKey, key1)
|
||||
@@ -82,10 +85,29 @@ var _ = Describe("Cert Manager", func() {
|
||||
})
|
||||
})
|
||||
|
||||
Context("verifying the server signature", func() {
|
||||
It("errors when the chain hasn't been set yet", func() {
|
||||
valid, err := cm.VerifyServerProof([]byte("proof"), []byte("chlo"), []byte("scfg"))
|
||||
Expect(err).To(MatchError(errNoCertificateChain))
|
||||
Context("verifying the server config signature", func() {
|
||||
It("returns false when the chain hasn't been set yet", func() {
|
||||
valid := cm.VerifyServerProof([]byte("proof"), []byte("chlo"), []byte("scfg"))
|
||||
Expect(valid).To(BeFalse())
|
||||
})
|
||||
|
||||
It("verifies the signature", func() {
|
||||
chlo := []byte("client hello")
|
||||
scfg := []byte("server config data")
|
||||
xcert1, err := x509.ParseCertificate(cert1)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
cm.chain = []*x509.Certificate{xcert1}
|
||||
proof, err := signServerProof(&tls.Certificate{PrivateKey: key1}, chlo, scfg)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
valid := cm.VerifyServerProof(proof, chlo, scfg)
|
||||
Expect(valid).To(BeTrue())
|
||||
})
|
||||
|
||||
It("rejects an invalid signature", func() {
|
||||
xcert1, err := x509.ParseCertificate(cert1)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
cm.chain = []*x509.Certificate{xcert1}
|
||||
valid := cm.VerifyServerProof([]byte("invalid proof"), []byte("chlo"), []byte("scfg"))
|
||||
Expect(valid).To(BeFalse())
|
||||
})
|
||||
})
|
||||
|
||||
@@ -156,28 +156,17 @@ func (h *cryptoSetupClient) handleREJMessage(cryptoData map[Tag][]byte) error {
|
||||
}
|
||||
|
||||
if h.serverConfig != nil && len(h.proof) != 0 && h.certManager.GetLeafCert() != nil {
|
||||
return h.verifyServerConfigSignature()
|
||||
validProof := h.certManager.VerifyServerProof(h.proof, h.chloForSignature, h.serverConfig.Get())
|
||||
if !validProof {
|
||||
return qerr.ProofInvalid
|
||||
}
|
||||
|
||||
h.serverVerified = true
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *cryptoSetupClient) verifyServerConfigSignature() error {
|
||||
validProof, err := h.certManager.VerifyServerProof(h.proof, h.chloForSignature, h.serverConfig.Get())
|
||||
if err != nil {
|
||||
return qerr.Error(qerr.InvalidCryptoMessageParameter, "Certificate data invalid")
|
||||
}
|
||||
if !validProof {
|
||||
return qerr.ProofInvalid
|
||||
}
|
||||
|
||||
// TODO: verify certificate chain
|
||||
|
||||
h.serverVerified = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *cryptoSetupClient) handleSHLOMessage(cryptoData map[Tag][]byte) error {
|
||||
serverPubs, ok := cryptoData[TagPUBS]
|
||||
if !ok {
|
||||
|
||||
@@ -42,13 +42,15 @@ func pemBlockForCert(certDER []byte) *pem.Block {
|
||||
|
||||
type mockCertManager struct {
|
||||
setDataCalledWith []byte
|
||||
leafCert []byte
|
||||
setDataError error
|
||||
|
||||
setDataError error
|
||||
verifyServerProofError error
|
||||
verifyServerProofValue bool
|
||||
leafCert []byte
|
||||
|
||||
verifyError error
|
||||
verifyServerProofResult bool
|
||||
verifyServerProofCalled bool
|
||||
|
||||
verifyError error
|
||||
verifyCalled bool
|
||||
}
|
||||
|
||||
func (m *mockCertManager) SetData(data []byte) error {
|
||||
@@ -60,11 +62,13 @@ func (m *mockCertManager) GetLeafCert() []byte {
|
||||
return m.leafCert
|
||||
}
|
||||
|
||||
func (m *mockCertManager) VerifyServerProof(proof, chlo, serverConfigData []byte) (bool, error) {
|
||||
return m.verifyServerProofValue, m.verifyServerProofError
|
||||
func (m *mockCertManager) VerifyServerProof(proof, chlo, serverConfigData []byte) bool {
|
||||
m.verifyServerProofCalled = true
|
||||
return m.verifyServerProofResult
|
||||
}
|
||||
|
||||
func (m *mockCertManager) Verify(hostname string) error {
|
||||
m.verifyCalled = true
|
||||
return m.verifyError
|
||||
}
|
||||
|
||||
@@ -162,32 +166,65 @@ var _ = Describe("Crypto setup", func() {
|
||||
Expect(err).To(MatchError(qerr.Error(qerr.InvalidCryptoMessageParameter, "Certificate data invalid")))
|
||||
})
|
||||
|
||||
It("returns a ProofInvalid error if the certificate chain is not valid", func() {
|
||||
tagMap[TagCERT] = []byte("cert")
|
||||
certManager.verifyError = errors.New("invalid")
|
||||
err := cs.handleREJMessage(tagMap)
|
||||
Expect(err).To(MatchError(qerr.ProofInvalid))
|
||||
Context("verifying the certificate chain", func() {
|
||||
It("returns a ProofInvalid error if the certificate chain is not valid", func() {
|
||||
tagMap[TagCERT] = []byte("cert")
|
||||
certManager.verifyError = errors.New("invalid")
|
||||
err := cs.handleREJMessage(tagMap)
|
||||
Expect(err).To(MatchError(qerr.ProofInvalid))
|
||||
})
|
||||
|
||||
It("verifies the certificate", func() {
|
||||
certManager.verifyServerProofResult = true
|
||||
tagMap[TagCERT] = []byte("cert")
|
||||
err := cs.handleREJMessage(tagMap)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(certManager.verifyCalled).To(BeTrue())
|
||||
})
|
||||
})
|
||||
|
||||
It("verifies the signature", func() {
|
||||
certManager.verifyServerProofValue = true
|
||||
certManager.verifyServerProofError = nil
|
||||
err := cs.verifyServerConfigSignature()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
Context("verifying the signature", func() {
|
||||
BeforeEach(func() {
|
||||
tagMap[TagCERT] = []byte("cert")
|
||||
tagMap[TagPROF] = []byte("proof")
|
||||
certManager.leafCert = []byte("leafcert")
|
||||
})
|
||||
|
||||
It("errors when it can't read the certificate", func() {
|
||||
certManager.verifyServerProofValue = true
|
||||
certManager.verifyServerProofError = errors.New("test error")
|
||||
err := cs.verifyServerConfigSignature()
|
||||
Expect(err).To(MatchError(qerr.Error(qerr.InvalidCryptoMessageParameter, "Certificate data invalid")))
|
||||
})
|
||||
It("rejects wrong signature", func() {
|
||||
certManager.verifyServerProofResult = false
|
||||
err := cs.handleREJMessage(tagMap)
|
||||
Expect(err).To(MatchError(qerr.ProofInvalid))
|
||||
Expect(certManager.verifyServerProofCalled).To(BeTrue())
|
||||
})
|
||||
|
||||
It("rejects wrong signatures", func() {
|
||||
certManager.verifyServerProofValue = false
|
||||
certManager.verifyServerProofError = nil
|
||||
err := cs.verifyServerConfigSignature()
|
||||
Expect(err).To(MatchError(qerr.ProofInvalid))
|
||||
It("accepts correct signatures", func() {
|
||||
certManager.verifyServerProofResult = true
|
||||
err := cs.handleREJMessage(tagMap)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(certManager.verifyServerProofCalled).To(BeTrue())
|
||||
})
|
||||
|
||||
It("doesn't try to verify the signature if the certificate is missing", func() {
|
||||
delete(tagMap, TagCERT)
|
||||
certManager.leafCert = nil
|
||||
err := cs.handleREJMessage(tagMap)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(certManager.verifyServerProofCalled).To(BeFalse())
|
||||
})
|
||||
|
||||
It("doesn't try to verify the signature if the server config is missing", func() {
|
||||
cs.serverConfig = nil
|
||||
err := cs.handleREJMessage(tagMap)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(certManager.verifyServerProofCalled).To(BeFalse())
|
||||
})
|
||||
|
||||
It("doesn't try to verify the signature if the signature is missing", func() {
|
||||
delete(tagMap, TagPROF)
|
||||
err := cs.handleREJMessage(tagMap)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(certManager.verifyServerProofCalled).To(BeFalse())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user