Test that we reject RSA ServerKeyExchange more thoroughly.
The old test just sent an empty ServerKeyExchange which is sufficient as we reject the message early. But be more thorough and implement the actual ephemeral key logic in the test server. Change-Id: I016658762e4502c928c051e14d69eea67b5a495f Reviewed-on: https://boringssl-review.googlesource.com/3650 Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
parent
03741f61d9
commit
a3e894921e
@ -289,7 +289,7 @@ func (s tls10MAC) MAC(digestBuf, seq, header, length, data []byte) []byte {
|
||||
}
|
||||
|
||||
func rsaKA(version uint16) keyAgreement {
|
||||
return &rsaKeyAgreement{}
|
||||
return &rsaKeyAgreement{version: version}
|
||||
}
|
||||
|
||||
func ecdheECDSAKA(version uint16) keyAgreement {
|
||||
|
@ -562,9 +562,10 @@ type ProtocolBugs struct {
|
||||
// retransmit at the record layer.
|
||||
SequenceNumberIncrement uint64
|
||||
|
||||
// RSAServerKeyExchange, if true, causes the server to send a
|
||||
// ServerKeyExchange message in the plain RSA key exchange.
|
||||
RSAServerKeyExchange bool
|
||||
// RSAEphemeralKey, if true, causes the server to send a
|
||||
// ServerKeyExchange message containing an ephemeral key (as in
|
||||
// RSA_EXPORT) in the plain RSA key exchange.
|
||||
RSAEphemeralKey bool
|
||||
|
||||
// SRTPMasterKeyIdentifer, if not empty, is the SRTP MKI value that the
|
||||
// client offers when negotiating SRTP. MKI support is still missing so
|
||||
|
@ -25,19 +25,73 @@ var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message")
|
||||
// rsaKeyAgreement implements the standard TLS key agreement where the client
|
||||
// encrypts the pre-master secret to the server's public key.
|
||||
type rsaKeyAgreement struct {
|
||||
version uint16
|
||||
clientVersion uint16
|
||||
exportKey *rsa.PrivateKey
|
||||
}
|
||||
|
||||
func (ka *rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
|
||||
// Save the client version for comparison later.
|
||||
ka.clientVersion = versionToWire(clientHello.vers, clientHello.isDTLS)
|
||||
|
||||
if config.Bugs.RSAServerKeyExchange {
|
||||
// Send an empty ServerKeyExchange message.
|
||||
return &serverKeyExchangeMsg{}, nil
|
||||
if !config.Bugs.RSAEphemeralKey {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
// Generate an ephemeral RSA key to use instead of the real
|
||||
// one, as in RSA_EXPORT.
|
||||
key, err := rsa.GenerateKey(config.rand(), 512)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ka.exportKey = key
|
||||
|
||||
modulus := key.N.Bytes()
|
||||
exponent := big.NewInt(int64(key.E)).Bytes()
|
||||
serverRSAParams := make([]byte, 0, 2+len(modulus)+2+len(exponent))
|
||||
serverRSAParams = append(serverRSAParams, byte(len(modulus)>>8), byte(len(modulus)))
|
||||
serverRSAParams = append(serverRSAParams, modulus...)
|
||||
serverRSAParams = append(serverRSAParams, byte(len(exponent)>>8), byte(len(exponent)))
|
||||
serverRSAParams = append(serverRSAParams, exponent...)
|
||||
|
||||
var tls12HashId uint8
|
||||
if ka.version >= VersionTLS12 {
|
||||
if tls12HashId, err = pickTLS12HashForSignature(signatureRSA, clientHello.signatureAndHashes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
digest, hashFunc, err := hashForServerKeyExchange(signatureRSA, tls12HashId, ka.version, clientHello.random, hello.random, serverRSAParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
privKey, ok := cert.PrivateKey.(*rsa.PrivateKey)
|
||||
if !ok {
|
||||
return nil, errors.New("RSA ephemeral key requires an RSA server private key")
|
||||
}
|
||||
sig, err := rsa.SignPKCS1v15(config.rand(), privKey, hashFunc, digest)
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to sign RSA parameters: " + err.Error())
|
||||
}
|
||||
|
||||
skx := new(serverKeyExchangeMsg)
|
||||
sigAndHashLen := 0
|
||||
if ka.version >= VersionTLS12 {
|
||||
sigAndHashLen = 2
|
||||
}
|
||||
skx.key = make([]byte, len(serverRSAParams)+sigAndHashLen+2+len(sig))
|
||||
copy(skx.key, serverRSAParams)
|
||||
k := skx.key[len(serverRSAParams):]
|
||||
if ka.version >= VersionTLS12 {
|
||||
k[0] = tls12HashId
|
||||
k[1] = signatureRSA
|
||||
k = k[2:]
|
||||
}
|
||||
k[0] = byte(len(sig) >> 8)
|
||||
k[1] = byte(len(sig))
|
||||
copy(k[2:], sig)
|
||||
|
||||
return skx, nil
|
||||
}
|
||||
|
||||
func (ka *rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
|
||||
@ -60,7 +114,11 @@ func (ka *rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certif
|
||||
ciphertext = ckx.ciphertext[2:]
|
||||
}
|
||||
|
||||
err = rsa.DecryptPKCS1v15SessionKey(config.rand(), cert.PrivateKey.(*rsa.PrivateKey), ciphertext, preMasterSecret)
|
||||
key := cert.PrivateKey.(*rsa.PrivateKey)
|
||||
if ka.exportKey != nil {
|
||||
key = ka.exportKey
|
||||
}
|
||||
err = rsa.DecryptPKCS1v15SessionKey(config.rand(), key, ciphertext, preMasterSecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -575,11 +575,11 @@ var testCases = []testCase{
|
||||
expectedError: ":WRONG_CIPHER_RETURNED:",
|
||||
},
|
||||
{
|
||||
name: "RSAServerKeyExchange",
|
||||
name: "RSAEphemeralKey",
|
||||
config: Config{
|
||||
CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
|
||||
Bugs: ProtocolBugs{
|
||||
RSAServerKeyExchange: true,
|
||||
RSAEphemeralKey: true,
|
||||
},
|
||||
},
|
||||
shouldFail: true,
|
||||
|
Loading…
Reference in New Issue
Block a user