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) {
|
||||
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")
|
||||
}
|
||||
|
@ -356,14 +356,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,
|
||||
}
|
||||
}
|
||||
|
@ -164,8 +164,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
|
||||
@ -1156,7 +1157,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:
|
||||
|
@ -499,7 +499,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
|
||||
|
@ -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())
|
||||
}
|
||||
@ -337,7 +341,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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user