crypto/tls: add RSASSA-PSS support for handshake messages
This adds support for RSASSA-PSS signatures in handshake messages as required by TLS 1.3. Even if TLS 1.2 is negotiated, it must support PSS when advertised in the Client Hello (this will be done later as the testdata will change). Updates #9671 Change-Id: I8006b92e017453ae408c153233ce5ccef99b5c3f
This commit is contained in:
parent
1850fd015e
commit
9f46cf9e2d
17
auth.go
17
auth.go
@ -26,9 +26,9 @@ func pickSignatureAlgorithm(pubkey crypto.PublicKey, peerSigAlgs, ourSigAlgs []S
|
|||||||
switch pubkey.(type) {
|
switch pubkey.(type) {
|
||||||
case *rsa.PublicKey:
|
case *rsa.PublicKey:
|
||||||
if tlsVersion < VersionTLS12 {
|
if tlsVersion < VersionTLS12 {
|
||||||
return 0, signatureRSA, crypto.MD5SHA1, nil
|
return 0, signaturePKCS1v15, crypto.MD5SHA1, nil
|
||||||
} else {
|
} else {
|
||||||
return PKCS1WithSHA1, signatureRSA, crypto.SHA1, nil
|
return PKCS1WithSHA1, signaturePKCS1v15, crypto.SHA1, nil
|
||||||
}
|
}
|
||||||
case *ecdsa.PublicKey:
|
case *ecdsa.PublicKey:
|
||||||
return ECDSAWithSHA1, signatureECDSA, crypto.SHA1, nil
|
return ECDSAWithSHA1, signatureECDSA, crypto.SHA1, nil
|
||||||
@ -47,7 +47,7 @@ func pickSignatureAlgorithm(pubkey crypto.PublicKey, peerSigAlgs, ourSigAlgs []S
|
|||||||
sigType := signatureFromSignatureScheme(sigAlg)
|
sigType := signatureFromSignatureScheme(sigAlg)
|
||||||
switch pubkey.(type) {
|
switch pubkey.(type) {
|
||||||
case *rsa.PublicKey:
|
case *rsa.PublicKey:
|
||||||
if sigType == signatureRSA {
|
if sigType == signaturePKCS1v15 || sigType == signatureRSAPSS {
|
||||||
return sigAlg, sigType, hashAlg, nil
|
return sigAlg, sigType, hashAlg, nil
|
||||||
}
|
}
|
||||||
case *ecdsa.PublicKey:
|
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) {
|
if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) {
|
||||||
return errors.New("tls: ECDSA verification failure")
|
return errors.New("tls: ECDSA verification failure")
|
||||||
}
|
}
|
||||||
case signatureRSA:
|
case signaturePKCS1v15:
|
||||||
pubKey, ok := pubkey.(*rsa.PublicKey)
|
pubKey, ok := pubkey.(*rsa.PublicKey)
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.New("tls: RSA signing requires a RSA public key")
|
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 {
|
if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil {
|
||||||
return err
|
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:
|
default:
|
||||||
return errors.New("tls: unknown signature algorithm")
|
return errors.New("tls: unknown signature algorithm")
|
||||||
}
|
}
|
||||||
|
@ -356,14 +356,14 @@ func rsaKA(version uint16) keyAgreement {
|
|||||||
|
|
||||||
func ecdheECDSAKA(version uint16) keyAgreement {
|
func ecdheECDSAKA(version uint16) keyAgreement {
|
||||||
return &ecdheKeyAgreement{
|
return &ecdheKeyAgreement{
|
||||||
sigType: signatureECDSA,
|
isRSA: false,
|
||||||
version: version,
|
version: version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ecdheRSAKA(version uint16) keyAgreement {
|
func ecdheRSAKA(version uint16) keyAgreement {
|
||||||
return &ecdheKeyAgreement{
|
return &ecdheKeyAgreement{
|
||||||
sigType: signatureRSA,
|
isRSA: true,
|
||||||
version: version,
|
version: version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,8 +164,9 @@ const (
|
|||||||
|
|
||||||
// Signature algorithms for TLS 1.2 (See RFC 5246, section A.4.1)
|
// Signature algorithms for TLS 1.2 (See RFC 5246, section A.4.1)
|
||||||
const (
|
const (
|
||||||
signatureRSA uint8 = 1
|
signaturePKCS1v15 uint8 = iota + 1
|
||||||
signatureECDSA uint8 = 3
|
signatureECDSA
|
||||||
|
signatureRSAPSS
|
||||||
)
|
)
|
||||||
|
|
||||||
// supportedSignatureAlgorithms contains the signature and hash algorithms that
|
// supportedSignatureAlgorithms contains the signature and hash algorithms that
|
||||||
@ -1156,7 +1157,9 @@ func isSupportedSignatureAlgorithm(sigAlg SignatureScheme, supportedSignatureAlg
|
|||||||
func signatureFromSignatureScheme(signatureAlgorithm SignatureScheme) uint8 {
|
func signatureFromSignatureScheme(signatureAlgorithm SignatureScheme) uint8 {
|
||||||
switch signatureAlgorithm {
|
switch signatureAlgorithm {
|
||||||
case PKCS1WithSHA1, PKCS1WithSHA256, PKCS1WithSHA384, PKCS1WithSHA512:
|
case PKCS1WithSHA1, PKCS1WithSHA256, PKCS1WithSHA384, PKCS1WithSHA512:
|
||||||
return signatureRSA
|
return signaturePKCS1v15
|
||||||
|
case PSSWithSHA256, PSSWithSHA384, PSSWithSHA512:
|
||||||
|
return signatureRSAPSS
|
||||||
case ECDSAWithSHA1, ECDSAWithP256AndSHA256, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512:
|
case ECDSAWithSHA1, ECDSAWithP256AndSHA256, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512:
|
||||||
return signatureECDSA
|
return signatureECDSA
|
||||||
default:
|
default:
|
||||||
|
@ -499,7 +499,11 @@ func (hs *clientHandshakeState) doFullHandshake() error {
|
|||||||
c.sendAlert(alertInternalError)
|
c.sendAlert(alertInternalError)
|
||||||
return err
|
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 {
|
if err != nil {
|
||||||
c.sendAlert(alertInternalError)
|
c.sendAlert(alertInternalError)
|
||||||
return err
|
return err
|
||||||
|
@ -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
|
// generates an ephemeral EC public/private key pair and signs it. The
|
||||||
// pre-master secret is then calculated using ECDH. The signature may
|
// pre-master secret is then calculated using ECDH. The signature may
|
||||||
// either be ECDSA or RSA.
|
// either be ECDSA or RSA.
|
||||||
type ecdheKeyAgreement struct {
|
type ecdheKeyAgreement struct {
|
||||||
version uint16
|
version uint16
|
||||||
sigType uint8
|
isRSA bool
|
||||||
privateKey []byte
|
privateKey []byte
|
||||||
curveid CurveID
|
curveid CurveID
|
||||||
|
|
||||||
@ -216,7 +216,7 @@ NextCandidate:
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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, errors.New("tls: certificate cannot be used with the selected cipher suite")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,7 +226,11 @@ NextCandidate:
|
|||||||
}
|
}
|
||||||
|
|
||||||
var sig []byte
|
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 {
|
if err != nil {
|
||||||
return nil, errors.New("tls: failed to sign ECDHE parameters: " + err.Error())
|
return nil, errors.New("tls: failed to sign ECDHE parameters: " + err.Error())
|
||||||
}
|
}
|
||||||
@ -337,7 +341,7 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if sigType != ka.sigType {
|
if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA {
|
||||||
return errServerKeyExchange
|
return errServerKeyExchange
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
prf.go
2
prf.go
@ -317,7 +317,7 @@ func (h finishedHash) hashForClientCertificate(sigType uint8, hashAlg crypto.Has
|
|||||||
}
|
}
|
||||||
|
|
||||||
if h.version == VersionSSL30 {
|
if h.version == VersionSSL30 {
|
||||||
if sigType != signatureRSA {
|
if sigType != signaturePKCS1v15 {
|
||||||
return nil, errors.New("tls: unsupported signature type for client certificate")
|
return nil, errors.New("tls: unsupported signature type for client certificate")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user