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
7 changes: 6 additions & 1 deletion src/crypto/tls/handshake_client_tls13.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"crypto"
"crypto/hmac"
"crypto/rsa"
"crypto/x509"
"errors"
"hash"
"sync/atomic"
Expand Down Expand Up @@ -481,7 +482,11 @@ func (hs *clientHandshakeStateTLS13) readServerCertificate() error {
return errors.New("tls: certificate used with invalid signature algorithm")
}
signed := signedMessage(sigHash, serverSignatureContext, hs.transcript)
if err := verifyHandshakeSignature(sigType, c.peerCertificates[0].PublicKey,
cert := c.peerCertificates[0]
if cert.KeyUsage != 0 && cert.KeyUsage&x509.KeyUsageDigitalSignature == 0 {
return errors.New("tls: invalid signature: the certificate cannot sign this kind of data")
}
if err := verifyHandshakeSignature(sigType, cert.PublicKey,
sigHash, signed, certVerify.signature); err != nil {
c.sendAlert(alertDecryptError)
return errors.New("tls: invalid signature by the server certificate: " + err.Error())
Expand Down
32 changes: 19 additions & 13 deletions src/crypto/tls/handshake_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -357,26 +357,26 @@ func (hs *serverHandshakeState) checkForResumption() bool {
if plaintext == nil {
return false
}
hs.sessionState = &sessionState{usedOldKey: usedOldKey}
ok := hs.sessionState.unmarshal(plaintext)
clientSessionState := &sessionState{usedOldKey: usedOldKey}
ok := clientSessionState.unmarshal(plaintext)
if !ok {
return false
}

createdAt := time.Unix(int64(hs.sessionState.createdAt), 0)
createdAt := time.Unix(int64(clientSessionState.createdAt), 0)
if c.config.time().Sub(createdAt) > maxSessionTicketLifetime {
return false
}

// Never resume a session for a different TLS version.
if c.vers != hs.sessionState.vers {
if c.vers != clientSessionState.vers {
return false
}

cipherSuiteOk := false
// Check that the client is still offering the ciphersuite in the session.
for _, id := range hs.clientHello.cipherSuites {
if id == hs.sessionState.cipherSuite {
if id == clientSessionState.cipherSuite {
cipherSuiteOk = true
break
}
Expand All @@ -385,14 +385,7 @@ func (hs *serverHandshakeState) checkForResumption() bool {
return false
}

// Check that we also support the ciphersuite from the session.
hs.suite = selectCipherSuite([]uint16{hs.sessionState.cipherSuite},
c.config.cipherSuites(), hs.cipherSuiteOk)
if hs.suite == nil {
return false
}

sessionHasClientCerts := len(hs.sessionState.certificates) != 0
sessionHasClientCerts := len(clientSessionState.certificates) != 0
needClientCerts := requiresClientCert(c.config.ClientAuth)
if needClientCerts && !sessionHasClientCerts {
return false
Expand All @@ -401,6 +394,15 @@ func (hs *serverHandshakeState) checkForResumption() bool {
return false
}

// Check that we also support the ciphersuite from the session.
hs.suite = selectCipherSuite([]uint16{clientSessionState.cipherSuite},
c.config.cipherSuites(), hs.cipherSuiteOk)
if hs.suite == nil {
return false
}

hs.sessionState = clientSessionState

return true
}

Expand Down Expand Up @@ -621,6 +623,10 @@ func (hs *serverHandshakeState) doFullHandshake() error {
}

signed := hs.finishedHash.hashForClientCertificate(sigType, sigHash, hs.masterSecret)
cert:=c.peerCertificates[0]
if cert.KeyUsage != 0 && cert.KeyUsage&x509.KeyUsageDigitalSignature == 0 {
return errors.New("tls: invalid signature: the certificate cannot sign this kind of data")
}
if err := verifyHandshakeSignature(sigType, pub, sigHash, signed, certVerify.signature); err != nil {
c.sendAlert(alertDecryptError)
return errors.New("tls: invalid signature by the client certificate: " + err.Error())
Expand Down
5 changes: 5 additions & 0 deletions src/crypto/tls/handshake_server_tls13.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"crypto"
"crypto/hmac"
"crypto/rsa"
"crypto/x509"
"errors"
"hash"
"io"
Expand Down Expand Up @@ -816,6 +817,10 @@ func (hs *serverHandshakeStateTLS13) readClientCertificate() error {
return errors.New("tls: client certificate used with invalid signature algorithm")
}
signed := signedMessage(sigHash, clientSignatureContext, hs.transcript)
cert := c.peerCertificates[0]
if cert.KeyUsage != 0 && cert.KeyUsage&x509.KeyUsageDigitalSignature == 0 {
return errors.New("tls: invalid signature: the certificate cannot sign this kind of data")
}
if err := verifyHandshakeSignature(sigType, c.peerCertificates[0].PublicKey,
sigHash, signed, certVerify.signature); err != nil {
c.sendAlert(alertDecryptError)
Expand Down
6 changes: 6 additions & 0 deletions src/crypto/tls/key_agreement.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello
return nil, nil, err
}

if cert.KeyUsage != 0 && cert.KeyUsage&x509.KeyUsageKeyEncipherment == 0 {
return nil,nil,errors.New("tls: invalid signature: the certificate cannot sign this kind of secret dkey")
}
encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
if err != nil {
return nil, nil, err
Expand Down Expand Up @@ -319,6 +322,9 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell
sig = sig[2:]

signed := hashForServerKeyExchange(sigType, sigHash, ka.version, clientHello.random, serverHello.random, serverECDHEParams)
if cert.KeyUsage != 0 && cert.KeyUsage&x509.KeyUsageDigitalSignature == 0 {
return errors.New("tls: invalid signature: the certificate cannot sign this kind of data")
}
if err := verifyHandshakeSignature(sigType, cert.PublicKey, sigHash, signed, sig); err != nil {
return errors.New("tls: invalid signature by the server certificate: " + err.Error())
}
Expand Down
3 changes: 3 additions & 0 deletions src/crypto/x509/root_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate
if parent.PublicKeyAlgorithm != ECDSA {
continue
}
if parent.KeyUsage != 0 && parent.KeyUsage&KeyUsageCertSign == 0 {
return nil,errors.New("x509: invalid signature: parent certificate cannot sign this kind of certificate")
}
if err := parent.CheckSignature(chain[i].SignatureAlgorithm,
chain[i].RawTBSCertificate, chain[i].Signature); err != nil {
return nil, err
Expand Down
30 changes: 29 additions & 1 deletion src/crypto/x509/x509.go
Original file line number Diff line number Diff line change
Expand Up @@ -555,15 +555,40 @@ func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) {
// KeyUsage represents the set of actions that are valid for a given key. It's
// a bitmap of the KeyUsage* constants.
type KeyUsage int

//Bits in the KeyUsage type are used as follows(refers to RFC 5280 4.2.1.3):
const (
//The digitalSignature bit is asserted when the subject public key
//is used for verifying digital signatures, other than signatures on
//certificates (bit 5) and CRLs (bit 6)
KeyUsageDigitalSignature KeyUsage = 1 << iota
//The contentCommitmentn bit is asserted when the subject public key is
//used to verify digital signatures, used to provide a non- repudiation
//service that protects against the signing entity falsely denying some
//action.
KeyUsageContentCommitment
//The keyEncipherment bit is asserted when the subject public key is
//used for enciphering private or secret keys, i.e., for key transport.
KeyUsageKeyEncipherment
//The dataEncipherment bit is asserted when the subject public key is used
//for directly enciphering raw user data without the use of an intermediate
//symmetric cipher.(Uncommon)
KeyUsageDataEncipherment
//The keyAgreement bit is asserted when the subject public key is used for
//key agreement. i.e., for Diffie-Hellman.
KeyUsageKeyAgreement
//The keyCertSign bit is asserted when the subject public key is used for verifying
//signatures on public key certificates. If the keyCertSign bit is asserted,
//then the cA bit in the basic constraints extension (Section 4.2.1.9) MUST
//also be asserted.
KeyUsageCertSign
//The cRLSign bit is asserted when the subject public key is used for
//verifying signatures on certificate revocation lists (e.g., CRLs, delta
//CRLs, or ARLs).
KeyUsageCRLSign
//The meaning of the encipherOnly/KeyUsageDecipherOnly bit is undefined in the
//absence of the keyAgreement bit. When the encipherOnly bit is asserted and
//the keyAgreement bit is also set, the subject public key may be used only for
//enciphering/deciphering data while performing key agreement.
KeyUsageEncipherOnly
KeyUsageDecipherOnly
)
Expand Down Expand Up @@ -923,6 +948,9 @@ func checkSignature(algo SignatureAlgorithm, signed, signature []byte, publicKey
// CheckCRLSignature checks that the signature in crl is from c.
func (c *Certificate) CheckCRLSignature(crl *pkix.CertificateList) error {
algo := getSignatureAlgorithmFromAI(crl.SignatureAlgorithm)
if c.KeyUsage != 0 && c.KeyUsage&KeyUsageCRLSign == 0 {
return errors.New("x509: invalid signature: this certificate cannot sign CRLs")
}
return c.CheckSignature(algo, crl.TBSCertList.Raw, crl.SignatureValue.RightAlign())
}

Expand Down