{"record":{"id":"b5697c2c92c0dbb9","repo":"golang/go","slug":"tls-client-s-finished-message-is-incorrect","errorCode":null,"errorMessage":"tls: client's Finished message is incorrect","messagePattern":"tls: client's Finished message is incorrect","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/crypto/tls/handshake_server.go","lineNumber":873,"sourceCode":"\n\t// finishedMsg is included in the transcript, but not until after we\n\t// check the client version, since the state before this message was\n\t// sent is used during verification.\n\tmsg, err := c.readHandshake(nil)\n\tif err != nil {\n\t\treturn err\n\t}\n\tclientFinished, ok := msg.(*finishedMsg)\n\tif !ok {\n\t\tc.sendAlert(alertUnexpectedMessage)\n\t\treturn unexpectedMessageError(clientFinished, msg)\n\t}\n\n\tverify := hs.finishedHash.clientSum(hs.masterSecret)\n\tif len(verify) != len(clientFinished.verifyData) ||\n\t\tsubtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {\n\t\tc.sendAlert(alertHandshakeFailure)\n\t\treturn errors.New(\"tls: client's Finished message is incorrect\")\n\t}\n\n\tif err := transcriptMsg(clientFinished, &hs.finishedHash); err != nil {\n\t\treturn err\n\t}\n\n\tcopy(out, verify)\n\treturn nil\n}\n\nfunc (hs *serverHandshakeState) sendSessionTicket() error {\n\tif !hs.hello.ticketSupported {\n\t\treturn nil\n\t}\n\n\tc := hs.c\n\tm := new(newSessionTicketMsg)\n","sourceCodeStart":855,"sourceCodeEnd":891,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/tls/handshake_server.go#L855-L891","documentation":"The server recomputed the client's Finished verify_data from the master secret and transcript, and it did not match the value sent by the client. A wrong Finished message means the client's view of the handshake diverges from the server's — usually a sign of tampering, an attacker injecting messages, or a buggy peer.","triggerScenarios":"In the server's finished-message processing: subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 (or length mismatch). The client computed verify_data with a different master secret or transcript hash.","commonSituations":"A MITM altering handshake records, an inconsistent master-secret derivation between client and server, a buggy client TLS library, or use of an incorrect PSK/session resumption. The handshake is aborted with handshake_failure.","solutions":["Check for middleboxes, proxies, or TLS-terminating load balancers that might alter handshake bytes — they break the transcript.","If using session resumption, ensure the ticket and PSK derivation are consistent between client and server.","Verify both peers run compatible TLS implementations (avoid ancient versions on either side).","Inspect cipher-suite negotiation for a mismatch that could cause divergent master-secret computation."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// No caller-side validation possible; Finished mismatch is a peer/transcript\n// integrity problem. Ensure no middlebox alters handshake bytes.","typeGuard":null,"tryCatchPattern":"// Server: treat as a potential MITM or bug; do not silently retry.\nif err != nil && strings.Contains(err.Error(), \"Finished message is incorrect\") {\n    log.Error(\"Finished verification failed — possible tampering\",\n        \"remote\", conn.RemoteAddr(), \"err\", err)\n    return err\n}","preventionTips":["Audit all TLS-terminating intermediates for handshake-record alteration.","Keep session-ticket/PSK derivation consistent across replicas.","Update all peers to compatible TLS library versions."],"tags":["tls","server-handshake","finished-message","transcript","handshake-failure","tls12"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:17:08.281Z"}