Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions client-state-machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,7 @@ func (state clientStateWaitCV) Next(hr handshakeMessageReader) (HandshakeState,
logf(logTypeHandshake, "Handshake Hash to be verified: [%d] %x", len(hcv), hcv)

serverPublicKey := state.serverCertificate.CertificateList[0].CertData.PublicKey
if err := certVerify.Verify(serverPublicKey, hcv); err != nil {
if err := certVerify.Verify(true, serverPublicKey, hcv); err != nil {
logf(logTypeHandshake, "[ClientStateWaitCV] Server signature failed to verify")
return nil, nil, AlertHandshakeFailure
}
Expand Down Expand Up @@ -1021,7 +1021,7 @@ func (state clientStateWaitFinished) Next(hr handshakeMessageReader) (HandshakeS
certificateVerify := &CertificateVerifyBody{Algorithm: certScheme}
logf(logTypeHandshake, "Creating CertVerify: %04x %v", certScheme, state.cryptoParams.Hash)

err = certificateVerify.Sign(cert.PrivateKey, hcv)
err = certificateVerify.Sign(false, cert.PrivateKey, hcv)
if err != nil {
logf(logTypeHandshake, "[ClientStateWaitFinished] Error signing CertificateVerify [%v]", err)
return nil, nil, AlertInternalError
Expand Down
2 changes: 2 additions & 0 deletions crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,8 @@ func HkdfExtract(hash crypto.Hash, saltIn, input []byte) []byte {
}

const (
clientCertVerifyContext = "TLS 1.3, client CertificateVerify"
serverCertVerifyContext = "TLS 1.3, server CertificateVerify"
labelExternalBinder = "ext binder"
labelResumptionBinder = "res binder"
labelEarlyTrafficSecret = "c e traffic"
Expand Down
21 changes: 10 additions & 11 deletions handshake-messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ func (ch *ClientHelloBody) Unmarshal(data []byte) (int, error) {
return read, nil
}

// TODO: File a spec bug to clarify this
func (ch ClientHelloBody) Truncated() ([]byte, error) {
if len(ch.Extensions) == 0 {
return nil, fmt.Errorf("tls.clienthello.truncate: No extensions")
Expand Down Expand Up @@ -205,8 +204,6 @@ func (sh *ServerHelloBody) Unmarshal(data []byte) (int, error) {
//
// For similar reasons, we don't use the `syntax` module here, because this
// struct doesn't map well to standard TLS presentation language concepts.
//
// TODO: File a spec bug
type FinishedBody struct {
VerifyDataLen int
VerifyData []byte
Expand Down Expand Up @@ -351,26 +348,28 @@ func (cv *CertificateVerifyBody) Unmarshal(data []byte) (int, error) {
return syntax.Unmarshal(data, cv)
}

func (cv *CertificateVerifyBody) EncodeSignatureInput(data []byte) []byte {
// TODO: Change context for client auth
// TODO: Put this in a const
const context = "TLS 1.3, server CertificateVerify"
func (cv *CertificateVerifyBody) EncodeSignatureInput(server bool, data []byte) []byte {
context := clientCertVerifyContext
if server {
context = serverCertVerifyContext
}

sigInput := bytes.Repeat([]byte{0x20}, 64)
sigInput = append(sigInput, []byte(context)...)
sigInput = append(sigInput, []byte{0}...)
sigInput = append(sigInput, data...)
return sigInput
}

func (cv *CertificateVerifyBody) Sign(privateKey crypto.Signer, handshakeHash []byte) (err error) {
sigInput := cv.EncodeSignatureInput(handshakeHash)
func (cv *CertificateVerifyBody) Sign(server bool, privateKey crypto.Signer, handshakeHash []byte) (err error) {
sigInput := cv.EncodeSignatureInput(server, handshakeHash)
cv.Signature, err = sign(cv.Algorithm, privateKey, sigInput)
logf(logTypeHandshake, "Signed: alg=[%04x] sigInput=[%x], sig=[%x]", cv.Algorithm, sigInput, cv.Signature)
return
}

func (cv *CertificateVerifyBody) Verify(publicKey crypto.PublicKey, handshakeHash []byte) error {
sigInput := cv.EncodeSignatureInput(handshakeHash)
func (cv *CertificateVerifyBody) Verify(server bool, publicKey crypto.PublicKey, handshakeHash []byte) error {
sigInput := cv.EncodeSignatureInput(server, handshakeHash)
logf(logTypeHandshake, "About to verify: alg=[%04x] sigInput=[%x], sig=[%x]", cv.Algorithm, sigInput, cv.Signature)
return verify(cv.Algorithm, publicKey, sigInput, cv.Signature)
}
Expand Down
29 changes: 19 additions & 10 deletions handshake-messages_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -539,29 +539,38 @@ func TestCertificateVerifyMarshalUnmarshal(t *testing.T) {
_, err = cv.Unmarshal(certVerifyValid[:5])
assertError(t, err, "Unmarshaled a CertificateVerify with no header")

// Test successful sign / verify round-trip
certVerifyValidIn.Algorithm = RSA_PSS_SHA256
err = certVerifyValidIn.Sign(privRSA, handshakeHash)
assertNotError(t, err, "Failed to sign CertificateVerify")

// Test sign failure on algorithm
originalAlg := certVerifyValidIn.Algorithm
certVerifyValidIn.Algorithm = SignatureScheme(0)
err = certVerifyValidIn.Sign(privRSA, handshakeHash)
err = certVerifyValidIn.Sign(true, privRSA, handshakeHash)
assertError(t, err, "Signed CertificateVerify despite bad algorithm")
certVerifyValidIn.Algorithm = originalAlg

// Test successful verify
// Test successful sign / verify round trip (client side)
certVerifyValidIn = CertificateVerifyBody{Algorithm: RSA_PSS_SHA256}
err = certVerifyValidIn.Sign(privRSA, handshakeHash)
err = certVerifyValidIn.Sign(false, privRSA, handshakeHash)
assertNotError(t, err, "Failed to sign CertificateVerify")
err = certVerifyValidIn.Verify(privRSA.Public(), handshakeHash)
err = certVerifyValidIn.Verify(false, privRSA.Public(), handshakeHash)
assertNotError(t, err, "Failed to verify CertificateVerify")

// Test successful sign / verify round trip (server side)
certVerifyValidIn = CertificateVerifyBody{Algorithm: RSA_PSS_SHA256}
err = certVerifyValidIn.Sign(true, privRSA, handshakeHash)
assertNotError(t, err, "Failed to sign CertificateVerify")
err = certVerifyValidIn.Verify(true, privRSA.Public(), handshakeHash)
assertNotError(t, err, "Failed to verify CertificateVerify")

// Test verify failure on client/server difference
certVerifyValidIn = CertificateVerifyBody{Algorithm: RSA_PSS_SHA256}
err = certVerifyValidIn.Sign(true, privRSA, handshakeHash)
assertNotError(t, err, "Failed to sign CertificateVerify")
err = certVerifyValidIn.Verify(false, privRSA.Public(), handshakeHash)
assertError(t, err, "Accpepted CertificateVerify in wrong context")

// Test verify failure on bad algorithm
originalAlg = certVerifyValidIn.Algorithm
certVerifyValidIn.Algorithm = SignatureScheme(0)
err = certVerifyValidIn.Verify(privRSA.Public(), handshakeHash)
err = certVerifyValidIn.Verify(true, privRSA.Public(), handshakeHash)
assertError(t, err, "Verified CertificateVerify despite bad hash algorithm")
certVerifyValidIn.Algorithm = originalAlg
}
Expand Down
4 changes: 2 additions & 2 deletions server-state-machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -665,7 +665,7 @@ func (state serverStateNegotiated) Next(_ handshakeMessageReader) (HandshakeStat
hcv := handshakeHash.Sum(nil)
logf(logTypeHandshake, "Handshake Hash to be verified: [%d] %x", len(hcv), hcv)

err = certificateVerify.Sign(state.cert.PrivateKey, hcv)
err = certificateVerify.Sign(true, state.cert.PrivateKey, hcv)
if err != nil {
logf(logTypeHandshake, "[ServerStateNegotiated] Error signing CertificateVerify [%v]", err)
return nil, nil, AlertInternalError
Expand Down Expand Up @@ -1061,7 +1061,7 @@ func (state serverStateWaitCV) Next(hr handshakeMessageReader) (HandshakeState,
logf(logTypeHandshake, "Handshake Hash to be verified: [%d] %x", len(hcv), hcv)

clientPublicKey := state.clientCertificate.CertificateList[0].CertData.PublicKey
if err := certVerify.Verify(clientPublicKey, hcv); err != nil {
if err := certVerify.Verify(false, clientPublicKey, hcv); err != nil {
logf(logTypeHandshake, "[ServerStateWaitCV] Failure in client auth verification [%v]", err)
return nil, nil, AlertHandshakeFailure
}
Expand Down
1 change: 1 addition & 0 deletions tls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ func TestExchangeData(t *testing.T) {

srv := <-srvCh
assertNotNil(t, srv, "Server should have completed handshake")
assertNotError(t, serr, "Error in server handshake")

buf := make([]byte, 16)
buf = buf[0:6]
Expand Down