()
| 541 | } |
| 542 | |
| 543 | func (hs *clientHandshakeStateTLS13) sendClientCertificate() error { |
| 544 | c := hs.c |
| 545 | |
| 546 | if hs.certReq == nil { |
| 547 | return nil |
| 548 | } |
| 549 | |
| 550 | cert, err := c.getClientCertificate(&CertificateRequestInfo{ |
| 551 | AcceptableCAs: hs.certReq.certificateAuthorities, |
| 552 | SignatureSchemes: hs.certReq.supportedSignatureAlgorithms, |
| 553 | Version: c.vers, |
| 554 | ctx: hs.ctx, |
| 555 | }) |
| 556 | if err != nil { |
| 557 | return err |
| 558 | } |
| 559 | |
| 560 | certMsg := new(certificateMsgTLS13) |
| 561 | |
| 562 | certMsg.certificate = *cert |
| 563 | certMsg.scts = hs.certReq.scts && len(cert.SignedCertificateTimestamps) > 0 |
| 564 | certMsg.ocspStapling = hs.certReq.ocspStapling && len(cert.OCSPStaple) > 0 |
| 565 | |
| 566 | hs.transcript.Write(certMsg.marshal()) |
| 567 | if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil { |
| 568 | return err |
| 569 | } |
| 570 | |
| 571 | // If we sent an empty certificate message, skip the CertificateVerify. |
| 572 | if len(cert.Certificate) == 0 { |
| 573 | return nil |
| 574 | } |
| 575 | |
| 576 | certVerifyMsg := new(certificateVerifyMsg) |
| 577 | certVerifyMsg.hasSignatureAlgorithm = true |
| 578 | |
| 579 | certVerifyMsg.signatureAlgorithm, err = selectSignatureScheme(c.vers, cert, hs.certReq.supportedSignatureAlgorithms) |
| 580 | if err != nil { |
| 581 | // getClientCertificate returned a certificate incompatible with the |
| 582 | // CertificateRequestInfo supported signature algorithms. |
| 583 | c.sendAlert(alertHandshakeFailure) |
| 584 | return err |
| 585 | } |
| 586 | |
| 587 | sigType, sigHash, err := typeAndHashFromSignatureScheme(certVerifyMsg.signatureAlgorithm) |
| 588 | if err != nil { |
| 589 | return c.sendAlert(alertInternalError) |
| 590 | } |
| 591 | |
| 592 | signed := signedMessage(sigHash, clientSignatureContext, hs.transcript) |
| 593 | signOpts := crypto.SignerOpts(sigHash) |
| 594 | if sigType == signatureRSAPSS { |
| 595 | signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: sigHash} |
| 596 | } |
| 597 | sig, err := cert.PrivateKey.(crypto.Signer).Sign(c.config.rand(), signed, signOpts) |
| 598 | if err != nil { |
| 599 | c.sendAlert(alertInternalError) |
| 600 | return errors.New("tls: failed to sign handshake: " + err.Error()) |
no test coverage detected