diff --git a/src/crypto/tls/auth.go b/src/crypto/tls/auth.go index 1e0cf23298cdc9..742013b27cc981 100644 --- a/src/crypto/tls/auth.go +++ b/src/crypto/tls/auth.go @@ -26,9 +26,9 @@ func pickSignatureAlgorithm(pubkey crypto.PublicKey, peerSigAlgs, ourSigAlgs []S switch pubkey.(type) { case *rsa.PublicKey: if tlsVersion < VersionTLS12 { - return 0, signatureRSA, crypto.MD5SHA1, nil + return 0, signaturePKCS1v15, crypto.MD5SHA1, nil } else { - return PKCS1WithSHA1, signatureRSA, crypto.SHA1, nil + return PKCS1WithSHA1, signaturePKCS1v15, crypto.SHA1, nil } case *ecdsa.PublicKey: return ECDSAWithSHA1, signatureECDSA, crypto.SHA1, nil @@ -47,7 +47,7 @@ func pickSignatureAlgorithm(pubkey crypto.PublicKey, peerSigAlgs, ourSigAlgs []S sigType := signatureFromSignatureScheme(sigAlg) switch pubkey.(type) { case *rsa.PublicKey: - if sigType == signatureRSA { + if sigType == signaturePKCS1v15 || sigType == signatureRSAPSS { return sigAlg, sigType, hashAlg, nil } case *ecdsa.PublicKey: @@ -78,7 +78,7 @@ func verifyHandshakeSignature(sigType uint8, pubkey crypto.PublicKey, hashFunc c if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) { return errors.New("tls: ECDSA verification failure") } - case signatureRSA: + case signaturePKCS1v15: pubKey, ok := pubkey.(*rsa.PublicKey) if !ok { return errors.New("tls: RSA signing requires a RSA public key") @@ -86,6 +86,15 @@ func verifyHandshakeSignature(sigType uint8, pubkey crypto.PublicKey, hashFunc c if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil { return err } + case signatureRSAPSS: + pubKey, ok := pubkey.(*rsa.PublicKey) + if !ok { + return errors.New("tls: RSA signing requires a RSA public key") + } + signOpts := &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash} + if err := rsa.VerifyPSS(pubKey, hashFunc, digest, sig, signOpts); err != nil { + return err + } default: return errors.New("tls: unknown signature algorithm") } diff --git a/src/crypto/tls/cipher_suites.go b/src/crypto/tls/cipher_suites.go index beb0f1926d8994..a90ee7cdace94a 100644 --- a/src/crypto/tls/cipher_suites.go +++ b/src/crypto/tls/cipher_suites.go @@ -333,14 +333,14 @@ func rsaKA(version uint16) keyAgreement { func ecdheECDSAKA(version uint16) keyAgreement { return &ecdheKeyAgreement{ - sigType: signatureECDSA, + isRSA: false, version: version, } } func ecdheRSAKA(version uint16) keyAgreement { return &ecdheKeyAgreement{ - sigType: signatureRSA, + isRSA: true, version: version, } } diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go index d4b0286b853929..8e25fa97039c18 100644 --- a/src/crypto/tls/common.go +++ b/src/crypto/tls/common.go @@ -129,8 +129,9 @@ const ( // Signature algorithms for TLS 1.2 (See RFC 5246, section A.4.1) const ( - signatureRSA uint8 = 1 - signatureECDSA uint8 = 3 + signaturePKCS1v15 uint8 = iota + 1 + signatureECDSA + signatureRSAPSS ) // supportedSignatureAlgorithms contains the signature and hash algorithms that @@ -969,7 +970,9 @@ func isSupportedSignatureAlgorithm(sigAlg SignatureScheme, supportedSignatureAlg func signatureFromSignatureScheme(signatureAlgorithm SignatureScheme) uint8 { switch signatureAlgorithm { case PKCS1WithSHA1, PKCS1WithSHA256, PKCS1WithSHA384, PKCS1WithSHA512: - return signatureRSA + return signaturePKCS1v15 + case PSSWithSHA256, PSSWithSHA384, PSSWithSHA512: + return signatureRSAPSS case ECDSAWithSHA1, ECDSAWithP256AndSHA256, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512: return signatureECDSA default: diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go index aabbbf828e1822..c8c1f48343fded 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go @@ -485,7 +485,11 @@ func (hs *clientHandshakeState) doFullHandshake() error { c.sendAlert(alertInternalError) return err } - certVerify.signature, err = key.Sign(c.config.rand(), digest, hashFunc) + signOpts := crypto.SignerOpts(hashFunc) + if sigType == signatureRSAPSS { + signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: hashFunc} + } + certVerify.signature, err = key.Sign(c.config.rand(), digest, signOpts) if err != nil { c.sendAlert(alertInternalError) return err diff --git a/src/crypto/tls/key_agreement.go b/src/crypto/tls/key_agreement.go index 72c2f1bce1382f..aa430cf5999bec 100644 --- a/src/crypto/tls/key_agreement.go +++ b/src/crypto/tls/key_agreement.go @@ -138,13 +138,13 @@ func curveForCurveID(id CurveID) (elliptic.Curve, bool) { } -// ecdheRSAKeyAgreement implements a TLS key agreement where the server +// ecdheKeyAgreement implements a TLS key agreement where the server // generates an ephemeral EC public/private key pair and signs it. The // pre-master secret is then calculated using ECDH. The signature may // either be ECDSA or RSA. type ecdheKeyAgreement struct { version uint16 - sigType uint8 + isRSA bool privateKey []byte curveid CurveID @@ -216,7 +216,7 @@ NextCandidate: if err != nil { return nil, err } - if sigType != ka.sigType { + if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA { return nil, errors.New("tls: certificate cannot be used with the selected cipher suite") } @@ -226,7 +226,11 @@ NextCandidate: } var sig []byte - sig, err = priv.Sign(config.rand(), digest, hashFunc) + signOpts := crypto.SignerOpts(hashFunc) + if sigType == signatureRSAPSS { + signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: hashFunc} + } + sig, err = priv.Sign(config.rand(), digest, signOpts) if err != nil { return nil, errors.New("tls: failed to sign ECDHE parameters: " + err.Error()) } @@ -334,7 +338,7 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell if err != nil { return err } - if sigType != ka.sigType { + if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA { return errServerKeyExchange } diff --git a/src/crypto/tls/prf.go b/src/crypto/tls/prf.go index 53cf04a1c06fb4..07519097917eb8 100644 --- a/src/crypto/tls/prf.go +++ b/src/crypto/tls/prf.go @@ -317,7 +317,7 @@ func (h finishedHash) hashForClientCertificate(sigType uint8, hashAlg crypto.Has } if h.version == VersionSSL30 { - if sigType != signatureRSA { + if sigType != signaturePKCS1v15 { return nil, errors.New("tls: unsupported signature type for client certificate") }