Client authentication
This commit is contained in:
parent
e62ddc004c
commit
c6745f1879
124
13.go
124
13.go
@ -792,6 +792,87 @@ func (hs *clientHandshakeState) verifyPeerCertificate(certVerify *certificateVer
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (hs *clientHandshakeState) getCertificate13(certReq *certificateRequestMsg13) (*Certificate, error) {
|
||||||
|
certReq12 := &certificateRequestMsg{
|
||||||
|
hasSignatureAndHash: true,
|
||||||
|
supportedSignatureAlgorithms: certReq.supportedSignatureAlgorithms,
|
||||||
|
certificateAuthorities: certReq.certificateAuthorities,
|
||||||
|
}
|
||||||
|
|
||||||
|
var rsaAvail, ecdsaAvail bool
|
||||||
|
for _, sigAlg := range certReq.supportedSignatureAlgorithms {
|
||||||
|
switch signatureFromSignatureScheme(sigAlg) {
|
||||||
|
case signaturePKCS1v15, signatureRSAPSS:
|
||||||
|
rsaAvail = true
|
||||||
|
case signatureECDSA:
|
||||||
|
ecdsaAvail = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if rsaAvail {
|
||||||
|
certReq12.certificateTypes = append(certReq12.certificateTypes, certTypeRSASign)
|
||||||
|
}
|
||||||
|
if ecdsaAvail {
|
||||||
|
certReq12.certificateTypes = append(certReq12.certificateTypes, certTypeECDSASign)
|
||||||
|
}
|
||||||
|
|
||||||
|
return hs.getCertificate(certReq12)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hs *clientHandshakeState) sendCertificate13(chainToSend *Certificate, certReq *certificateRequestMsg13) error {
|
||||||
|
c := hs.c
|
||||||
|
|
||||||
|
certEntries := []certificateEntry{}
|
||||||
|
for _, cert := range chainToSend.Certificate {
|
||||||
|
certEntries = append(certEntries, certificateEntry{data: cert})
|
||||||
|
}
|
||||||
|
certMsg := &certificateMsg13{certificates: certEntries}
|
||||||
|
|
||||||
|
hs.keySchedule.write(certMsg.marshal())
|
||||||
|
if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(certEntries) == 0 {
|
||||||
|
// No client cert available, nothing to sign.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
key, ok := chainToSend.PrivateKey.(crypto.Signer)
|
||||||
|
if !ok {
|
||||||
|
c.sendAlert(alertInternalError)
|
||||||
|
return fmt.Errorf("tls: client certificate private key of type %T does not implement crypto.Signer", chainToSend.PrivateKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
signatureAlgorithm, sigType, hashFunc, err := pickSignatureAlgorithm(key.Public(), certReq.supportedSignatureAlgorithms, hs.hello.supportedSignatureAlgorithms, c.vers)
|
||||||
|
if err != nil {
|
||||||
|
hs.c.sendAlert(alertHandshakeFailure)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
digest := prepareDigitallySigned(hashFunc, "TLS 1.3, client CertificateVerify", hs.keySchedule.transcriptHash.Sum(nil))
|
||||||
|
signOpts := crypto.SignerOpts(hashFunc)
|
||||||
|
if sigType == signatureRSAPSS {
|
||||||
|
signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: hashFunc}
|
||||||
|
}
|
||||||
|
signature, err := key.Sign(c.config.rand(), digest, signOpts)
|
||||||
|
if err != nil {
|
||||||
|
c.sendAlert(alertInternalError)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyMsg := &certificateVerifyMsg{
|
||||||
|
hasSignatureAndHash: true,
|
||||||
|
signatureAlgorithm: signatureAlgorithm,
|
||||||
|
signature: signature,
|
||||||
|
}
|
||||||
|
hs.keySchedule.write(verifyMsg.marshal())
|
||||||
|
if _, err := c.writeRecord(recordTypeHandshake, verifyMsg.marshal()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (hs *clientHandshakeState) doTLS13Handshake() error {
|
func (hs *clientHandshakeState) doTLS13Handshake() error {
|
||||||
c := hs.c
|
c := hs.c
|
||||||
hash := hashForSuite(hs.suite)
|
hash := hashForSuite(hs.suite)
|
||||||
@ -853,7 +934,23 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// TODO handle optional CertificateRequest
|
|
||||||
|
var chainToSend *Certificate
|
||||||
|
certReq, isCertRequested := msg.(*certificateRequestMsg13)
|
||||||
|
if isCertRequested {
|
||||||
|
hs.keySchedule.write(certReq.marshal())
|
||||||
|
|
||||||
|
if chainToSend, err = hs.getCertificate13(certReq); err != nil {
|
||||||
|
c.sendAlert(alertInternalError)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err = c.readHandshake()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
certMsg, ok := msg.(*certificateMsg13)
|
certMsg, ok := msg.(*certificateMsg13)
|
||||||
if !ok {
|
if !ok {
|
||||||
c.sendAlert(alertUnexpectedMessage)
|
c.sendAlert(alertUnexpectedMessage)
|
||||||
@ -898,10 +995,21 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
|
|||||||
}
|
}
|
||||||
hs.keySchedule.write(serverFinished.marshal())
|
hs.keySchedule.write(serverFinished.marshal())
|
||||||
|
|
||||||
// Server has authenticated itself, change our cipher.
|
// Server has authenticated itself. Calculate application traffic secrets.
|
||||||
|
hs.keySchedule.setSecret(nil) // derive master secret
|
||||||
|
appServerCipher, _ := hs.keySchedule.prepareCipher(secretApplicationServer)
|
||||||
|
appClientCipher, _ := hs.keySchedule.prepareCipher(secretApplicationClient)
|
||||||
|
|
||||||
|
// Change outbound handshake cipher for final step
|
||||||
c.out.setCipher(c.vers, clientCipher)
|
c.out.setCipher(c.vers, clientCipher)
|
||||||
|
|
||||||
// TODO optionally send a client cert
|
// Client auth requires sending a (possibly empty) Certificate followed
|
||||||
|
// by a CertificateVerify message (if there was an actual certificate).
|
||||||
|
if isCertRequested {
|
||||||
|
if err := hs.sendCertificate13(chainToSend, certReq); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Send Finished
|
// Send Finished
|
||||||
verifyData := hmacOfSum(hash, hs.keySchedule.transcriptHash, clientFinishedKey)
|
verifyData := hmacOfSum(hash, hs.keySchedule.transcriptHash, clientFinishedKey)
|
||||||
@ -912,16 +1020,14 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate application traffic secrets.
|
|
||||||
hs.keySchedule.setSecret(nil) // derive master secret
|
|
||||||
// TODO store initial traffic secret key for KeyUpdate
|
// TODO store initial traffic secret key for KeyUpdate
|
||||||
clientCipher, _ = hs.keySchedule.prepareCipher(secretApplicationClient)
|
|
||||||
serverCipher, _ = hs.keySchedule.prepareCipher(secretApplicationServer)
|
// Handshake done, set application traffic secret
|
||||||
c.out.setCipher(c.vers, clientCipher)
|
c.out.setCipher(c.vers, appClientCipher)
|
||||||
if c.hand.Len() > 0 {
|
if c.hand.Len() > 0 {
|
||||||
c.sendAlert(alertUnexpectedMessage)
|
c.sendAlert(alertUnexpectedMessage)
|
||||||
return errors.New("tls: unexpected data after handshake")
|
return errors.New("tls: unexpected data after handshake")
|
||||||
}
|
}
|
||||||
c.in.setCipher(c.vers, serverCipher)
|
c.in.setCipher(c.vers, appServerCipher)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user