diff --git a/13.go b/13.go index cfb2638..ad329d5 100644 --- a/13.go +++ b/13.go @@ -211,12 +211,26 @@ CurvePreferenceLoop: serverFinishedKey := hkdfExpandLabel(hash, sTrafficSecret, nil, "finished", hashSize) hs.clientFinishedKey = hkdfExpandLabel(hash, cTrafficSecret, nil, "finished", hashSize) + // EncryptedExtensions hs.keySchedule.write(hs.hello13Enc.marshal()) if _, err := c.writeRecord(recordTypeHandshake, hs.hello13Enc.marshal()); err != nil { return err } + // TODO: we should have 2 separated methods - one for full-handshake and the other for PSK-handshake if !c.didResume { + // Server MUST NOT send CertificateRequest if authenticating with PSK + if (c.config.ClientAuth >= RequestClientCert) { + + certReq := new(certificateRequestMsg13) + // extension 'signature_algorithms' MUST be specified + certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms13 + hs.keySchedule.write(certReq.marshal()) + if _, err := hs.c.writeRecord(recordTypeHandshake, certReq.marshal()); err != nil { + return err + } + } + if err := hs.sendCertificate13(); err != nil { return err } @@ -286,6 +300,43 @@ func (hs *serverHandshakeState) readClientFinished13(hasConfirmLock bool) error return err } + // client authentication + if certMsg, ok := msg.(*certificateMsg13); ok { + + hs.keySchedule.write(certMsg.marshal()) + pubKey, err := hs.processCertsFromClient13(certMsg) + if err != nil { + return err + } + + // 4.4.3: CertificateVerify MUST appear immediately after Certificate msg + msg, err = c.readHandshake() + if err != nil { + return err + } + + certVerify, ok := msg.(*certificateVerifyMsg); + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(certVerify, msg) + } + + if err = hs.verifyPeerCertificate(certVerify, pubKey); err != nil { + return err + } + hs.keySchedule.write(certVerify.marshal()) + + // Read next chunk + msg, err = c.readHandshake() + if err != nil { + return err + } + + } else if (c.config.ClientAuth >= RequestClientCert) && !c.didResume { + c.sendAlert(alertCertificateRequired) + return unexpectedMessageError(certMsg, msg) + } + clientFinished, ok := msg.(*finishedMsg) if !ok { c.sendAlert(alertUnexpectedMessage) @@ -767,6 +818,15 @@ func (hs *clientHandshakeState) processCertsFromServer13(certMsg *certificateMsg return hs.processCertsFromServer(certs) } +// TODO: Merge with function above +func (hs *serverHandshakeState) processCertsFromClient13(certMsg *certificateMsg13) (crypto.PublicKey, error) { + certs := make([][]byte, len(certMsg.certificates)) + for i, cert := range certMsg.certificates { + certs[i] = cert.data + } + return hs.processCertsFromClient(certs) +} + func (hs *clientHandshakeState) processEncryptedExtensions(ee *encryptedExtensionsMsg) error { c := hs.c if ee.alpnProtocol != "" { @@ -792,6 +852,22 @@ func (hs *clientHandshakeState) verifyPeerCertificate(certVerify *certificateVer return nil } +// TODO: Merge with function above +func (hs *serverHandshakeState) verifyPeerCertificate(certVerify *certificateVerifyMsg, pub crypto.PublicKey) error { + _, sigType, hashFunc, err := pickSignatureAlgorithm(pub, []SignatureScheme{certVerify.signatureAlgorithm}, supportedSignatureAlgorithms13, hs.c.vers) + if err != nil { + hs.c.sendAlert(alertHandshakeFailure) + return err + } + digest := prepareDigitallySigned(hashFunc, "TLS 1.3, client CertificateVerify", hs.keySchedule.transcriptHash.Sum(nil)) + err = verifyHandshakeSignature(sigType, pub, hashFunc, digest, certVerify.signature) + if err != nil { + hs.c.sendAlert(alertDecryptError) + return err + } + return nil +} + func (hs *clientHandshakeState) getCertificate13(certReq *certificateRequestMsg13) (*Certificate, error) { certReq12 := &certificateRequestMsg{ hasSignatureAndHash: true,