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
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:
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")
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")
}
rsaCert := &testRSAPrivateKey.PublicKey
ecdsaCert := &testECDSAPrivateKey.PublicKey
sigsPKCS1WithSHA := []SignatureScheme{PKCS1WithSHA256, PKCS1WithSHA1}
+ sigsPSSWithSHA := []SignatureScheme{PSSWithSHA256, PSSWithSHA384}
sigsECDSAWithSHA := []SignatureScheme{ECDSAWithP256AndSHA256, ECDSAWithSHA1}
tests := []struct {
}{
// Hash is fixed for RSA in TLS 1.1 and before.
// https://tools.ietf.org/html/rfc4346#page-44
- {rsaCert, nil, nil, VersionTLS11, 0, signatureRSA, crypto.MD5SHA1},
- {rsaCert, nil, nil, VersionTLS10, 0, signatureRSA, crypto.MD5SHA1},
- {rsaCert, nil, nil, VersionSSL30, 0, signatureRSA, crypto.MD5SHA1},
+ {rsaCert, nil, nil, VersionTLS11, 0, signaturePKCS1v15, crypto.MD5SHA1},
+ {rsaCert, nil, nil, VersionTLS10, 0, signaturePKCS1v15, crypto.MD5SHA1},
+ {rsaCert, nil, nil, VersionSSL30, 0, signaturePKCS1v15, crypto.MD5SHA1},
// Before TLS 1.2, there is no signature_algorithms extension
// nor field in CertificateRequest and digitally-signed and thus
// it should be ignored.
- {rsaCert, sigsPKCS1WithSHA, nil, VersionTLS11, 0, signatureRSA, crypto.MD5SHA1},
- {rsaCert, sigsPKCS1WithSHA, sigsPKCS1WithSHA, VersionTLS11, 0, signatureRSA, crypto.MD5SHA1},
+ {rsaCert, sigsPKCS1WithSHA, nil, VersionTLS11, 0, signaturePKCS1v15, crypto.MD5SHA1},
+ {rsaCert, sigsPKCS1WithSHA, sigsPKCS1WithSHA, VersionTLS11, 0, signaturePKCS1v15, crypto.MD5SHA1},
// Use SHA-1 for TLS 1.0 and 1.1 with ECDSA, see https://tools.ietf.org/html/rfc4492#page-20
{ecdsaCert, sigsPKCS1WithSHA, sigsPKCS1WithSHA, VersionTLS11, 0, signatureECDSA, crypto.SHA1},
{ecdsaCert, sigsPKCS1WithSHA, sigsPKCS1WithSHA, VersionTLS10, 0, signatureECDSA, crypto.SHA1},
// TLS 1.2 without signature_algorithms extension
// https://tools.ietf.org/html/rfc5246#page-47
- {rsaCert, nil, sigsPKCS1WithSHA, VersionTLS12, PKCS1WithSHA1, signatureRSA, crypto.SHA1},
+ {rsaCert, nil, sigsPKCS1WithSHA, VersionTLS12, PKCS1WithSHA1, signaturePKCS1v15, crypto.SHA1},
{ecdsaCert, nil, sigsPKCS1WithSHA, VersionTLS12, ECDSAWithSHA1, signatureECDSA, crypto.SHA1},
- {rsaCert, []SignatureScheme{PKCS1WithSHA1}, sigsPKCS1WithSHA, VersionTLS12, PKCS1WithSHA1, signatureRSA, crypto.SHA1},
- {rsaCert, []SignatureScheme{PKCS1WithSHA256}, sigsPKCS1WithSHA, VersionTLS12, PKCS1WithSHA256, signatureRSA, crypto.SHA256},
+ {rsaCert, []SignatureScheme{PKCS1WithSHA1}, sigsPKCS1WithSHA, VersionTLS12, PKCS1WithSHA1, signaturePKCS1v15, crypto.SHA1},
+ {rsaCert, []SignatureScheme{PKCS1WithSHA256}, sigsPKCS1WithSHA, VersionTLS12, PKCS1WithSHA256, signaturePKCS1v15, crypto.SHA256},
// "sha_hash" may denote hashes other than SHA-1
// https://tools.ietf.org/html/draft-ietf-tls-rfc4492bis-17#page-17
{ecdsaCert, []SignatureScheme{ECDSAWithSHA1}, sigsECDSAWithSHA, VersionTLS12, ECDSAWithSHA1, signatureECDSA, crypto.SHA1},
{ecdsaCert, []SignatureScheme{ECDSAWithP256AndSHA256}, sigsECDSAWithSHA, VersionTLS12, ECDSAWithP256AndSHA256, signatureECDSA, crypto.SHA256},
+
+ // RSASSA-PSS is defined in TLS 1.3 for TLS 1.2
+ // https://tools.ietf.org/html/draft-ietf-tls-tls13-21#page-45
+ {rsaCert, []SignatureScheme{PSSWithSHA256}, sigsPSSWithSHA, VersionTLS12, PSSWithSHA256, signatureRSAPSS, crypto.SHA256},
}
for testNo, test := range tests {
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,
}
}
// Rest of these are reserved by the TLS spec
)
-// Signature algorithms for TLS 1.2 (See RFC 5246, section A.4.1)
+// Signature algorithms (for internal signaling use). Starting at 16 to avoid overlap with
+// TLS 1.2 codepoints (RFC 5246, section A.4.1), with which these have nothing to do.
const (
- signatureRSA uint8 = 1
- signatureECDSA uint8 = 3
+ signaturePKCS1v15 uint8 = iota + 16
+ signatureECDSA
+ signatureRSAPSS
)
// supportedSignatureAlgorithms contains the signature and hash algorithms that
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:
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
}
}
}
+
+func TestRSAPSSKeyError(t *testing.T) {
+ // crypto/tls does not support the rsa_pss_pss_xxx SignatureSchemes. If support for
+ // public keys with OID RSASSA-PSS is added to crypto/x509, they will be misused with
+ // the rsa_pss_rsae_xxx SignatureSchemes. Assert that RSASSA-PSS certificates don't
+ // parse, or that they don't carry *rsa.PublicKey keys.
+ b, _ := pem.Decode([]byte(`
+-----BEGIN CERTIFICATE-----
+MIIDZTCCAhygAwIBAgIUCF2x0FyTgZG0CC9QTDjGWkB5vgEwPgYJKoZIhvcNAQEK
+MDGgDTALBglghkgBZQMEAgGhGjAYBgkqhkiG9w0BAQgwCwYJYIZIAWUDBAIBogQC
+AgDeMBIxEDAOBgNVBAMMB1JTQS1QU1MwHhcNMTgwNjI3MjI0NDM2WhcNMTgwNzI3
+MjI0NDM2WjASMRAwDgYDVQQDDAdSU0EtUFNTMIIBIDALBgkqhkiG9w0BAQoDggEP
+ADCCAQoCggEBANxDm0f76JdI06YzsjB3AmmjIYkwUEGxePlafmIASFjDZl/elD0Z
+/a7xLX468b0qGxLS5al7XCcEprSdsDR6DF5L520+pCbpfLyPOjuOvGmk9KzVX4x5
+b05YXYuXdsQ0Kjxcx2i3jjCday6scIhMJVgBZxTEyMj1thPQM14SHzKCd/m6HmCL
+QmswpH2yMAAcBRWzRpp/vdH5DeOJEB3aelq7094no731mrLUCHRiZ1htq8BDB3ou
+czwqgwspbqZ4dnMXl2MvfySQ5wJUxQwILbiuAKO2lVVPUbFXHE9pgtznNoPvKwQT
+JNcX8ee8WIZc2SEGzofjk3NpjR+2ADB2u3sCAwEAAaNTMFEwHQYDVR0OBBYEFNEz
+AdyJ2f+fU+vSCS6QzohnOnprMB8GA1UdIwQYMBaAFNEzAdyJ2f+fU+vSCS6Qzohn
+OnprMA8GA1UdEwEB/wQFMAMBAf8wPgYJKoZIhvcNAQEKMDGgDTALBglghkgBZQME
+AgGhGjAYBgkqhkiG9w0BAQgwCwYJYIZIAWUDBAIBogQCAgDeA4IBAQCjEdrR5aab
+sZmCwrMeKidXgfkmWvfuLDE+TCbaqDZp7BMWcMQXT9O0UoUT5kqgKj2ARm2pEW0Z
+H3Z1vj3bbds72qcDIJXp+l0fekyLGeCrX/CbgnMZXEP7+/+P416p34ChR1Wz4dU1
+KD3gdsUuTKKeMUog3plxlxQDhRQmiL25ygH1LmjLd6dtIt0GVRGr8lj3euVeprqZ
+bZ3Uq5eLfsn8oPgfC57gpO6yiN+UURRTlK3bgYvLh4VWB3XXk9UaQZ7Mq1tpXjoD
+HYFybkWzibkZp4WRo+Fa28rirH+/wHt0vfeN7UCceURZEx4JaxIIfe4ku7uDRhJi
+RwBA9Xk1KBNF
+-----END CERTIFICATE-----`))
+ if b == nil {
+ t.Fatal("Failed to decode certificate")
+ }
+ cert, err := x509.ParseCertificate(b.Bytes)
+ if err != nil {
+ return
+ }
+ if _, ok := cert.PublicKey.(*rsa.PublicKey); ok {
+ t.Error("A RSA-PSS certificate was parsed like a PKCS1 one, and it will be mistakenly used with rsa_pss_rsae_xxx signature algorithms")
+ }
+}
}
-// 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
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")
}
return nil, err
}
- 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())
}
if err != nil {
return err
}
- if sigType != ka.sigType {
+ if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA {
return errServerKeyExchange
}
}
if h.version == VersionSSL30 {
- if sigType != signatureRSA {
+ if sigType != signaturePKCS1v15 {
return nil, errors.New("tls: unsupported signature type for client certificate")
}