summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ssl/s3_clnt.c50
-rw-r--r--ssl/test/runner/cipher_suites.go2
-rw-r--r--ssl/test/runner/common.go5
-rw-r--r--ssl/test/runner/key_agreement.go73
-rw-r--r--ssl/test/runner/runner.go11
5 files changed, 87 insertions, 54 deletions
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 64bccfa..0c37f76 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -1293,55 +1293,7 @@ int ssl3_get_server_key_exchange(SSL *s)
}
}
- if (alg_k & SSL_kRSA)
- {
- CBS rsa_modulus, rsa_exponent;
-
- /* TODO(davidben): This was originally for export
- * reasons. Do we still need to support it? */
-
- if (!CBS_get_u16_length_prefixed(&server_key_exchange, &rsa_modulus) ||
- CBS_len(&rsa_modulus) == 0 ||
- !CBS_get_u16_length_prefixed(&server_key_exchange, &rsa_exponent) ||
- CBS_len(&rsa_exponent) == 0)
- {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DECODE_ERROR);
- goto f_err;
- }
-
- if ((rsa=RSA_new()) == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (!(rsa->n = BN_bin2bn(CBS_data(&rsa_modulus),
- CBS_len(&rsa_modulus), rsa->n)))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_BN_LIB);
- goto err;
- }
-
- if (!(rsa->e = BN_bin2bn(CBS_data(&rsa_exponent),
- CBS_len(&rsa_exponent), rsa->e)))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_BN_LIB);
- goto err;
- }
-
- /* this should be because we are using an export cipher */
- if (alg_a & SSL_aRSA)
- pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
- else
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- s->session->sess_cert->peer_rsa_tmp=rsa;
- rsa=NULL;
- }
- else if (alg_k & SSL_kEDH)
+ if (alg_k & SSL_kEDH)
{
CBS dh_p, dh_g, dh_Ys;
diff --git a/ssl/test/runner/cipher_suites.go b/ssl/test/runner/cipher_suites.go
index 5a3ac80..62b8100 100644
--- a/ssl/test/runner/cipher_suites.go
+++ b/ssl/test/runner/cipher_suites.go
@@ -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 {
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 6f146af..1f7e392 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -499,6 +499,11 @@ type ProtocolBugs struct {
// BadRenegotiationInfo causes the renegotiation extension value in a
// renegotiation handshake to be incorrect.
BadRenegotiationInfo 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
}
func (c *Config) serverInit() {
diff --git a/ssl/test/runner/key_agreement.go b/ssl/test/runner/key_agreement.go
index af54a8f..86202ae 100644
--- a/ssl/test/runner/key_agreement.go
+++ b/ssl/test/runner/key_agreement.go
@@ -25,10 +25,71 @@ 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{}
+type rsaKeyAgreement struct {
+ version uint16
+ exportKey *rsa.PrivateKey
+}
-func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
- return nil, nil
+func (ka *rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
+ if !config.Bugs.RSAEphemeralKey {
+ 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
+ }
+ var sig []byte
+ privKey, ok := cert.PrivateKey.(*rsa.PrivateKey)
+ if !ok {
+ return nil, errors.New("RSA requires a 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) {
@@ -51,7 +112,11 @@ func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certifi
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
}
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 4b43481..57213bb 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -492,6 +492,17 @@ var testCases = []testCase{
shouldFail: true,
expectedError: ":WRONG_CIPHER_RETURNED:",
},
+ {
+ name: "RSAEphemeralKey",
+ config: Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+ Bugs: ProtocolBugs{
+ RSAEphemeralKey: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_MESSAGE:",
+ },
}
func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {