Adding handling for KeyUpdate post-handshake message.

BUG=74

Change-Id: I72d52c1fbc3413e940dddbc0b20c7f22459da693
Reviewed-on: https://boringssl-review.googlesource.com/8981
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
Steven Valdez 2016-07-26 12:27:38 -04:00 committed by CQ bot account: commit-bot@chromium.org
parent 8e1c7be1a7
commit 1dc53d2840
6 changed files with 66 additions and 7 deletions

View File

@ -823,6 +823,10 @@ int tls13_set_traffic_key(SSL *ssl, enum tls_record_type_t type,
* zero on error. */ * zero on error. */
int tls13_set_handshake_traffic(SSL *ssl); int tls13_set_handshake_traffic(SSL *ssl);
/* tls13_rotate_traffic_key derives the next read or write traffic secret. It
* returns one on success and zero on error. */
int tls13_rotate_traffic_key(SSL *ssl, enum evp_aead_direction_t direction);
/* tls13_derive_traffic_secret_0 derives the initial application data traffic /* tls13_derive_traffic_secret_0 derives the initial application data traffic
* secret based on the handshake transcripts and |master_secret|. It returns one * secret based on the handshake transcripts and |master_secret|. It returns one
* on success and zero on error. */ * on success and zero on error. */

View File

@ -885,6 +885,10 @@ type ProtocolBugs struct {
// message. This only makes sense for a server. // message. This only makes sense for a server.
SendHelloRequestBeforeEveryHandshakeMessage bool SendHelloRequestBeforeEveryHandshakeMessage bool
// SendKeyUpdateBeforeEveryAppDataRecord, if true, causes a KeyUpdate
// handshake message to be sent before each application data record.
SendKeyUpdateBeforeEveryAppDataRecord bool
// RequireDHPublicValueLen causes a fatal error if the length (in // RequireDHPublicValueLen causes a fatal error if the length (in
// bytes) of the server's Diffie-Hellman public value is not equal to // bytes) of the server's Diffie-Hellman public value is not equal to
// this. // this.

View File

@ -1325,6 +1325,10 @@ func (c *Conn) Write(b []byte) (int, error) {
c.flushHandshake() c.flushHandshake()
} }
if c.config.Bugs.SendKeyUpdateBeforeEveryAppDataRecord {
c.sendKeyUpdateLocked()
}
// SSL 3.0 and TLS 1.0 are susceptible to a chosen-plaintext // SSL 3.0 and TLS 1.0 are susceptible to a chosen-plaintext
// attack when using block mode ciphers due to predictable IVs. // attack when using block mode ciphers due to predictable IVs.
// This can be prevented by splitting each Application Data // This can be prevented by splitting each Application Data
@ -1394,7 +1398,7 @@ func (c *Conn) handlePostHandshakeMessage() error {
} }
if _, ok := msg.(*keyUpdateMsg); ok { if _, ok := msg.(*keyUpdateMsg); ok {
c.in.doKeyUpdate(c, true) c.in.doKeyUpdate(c, false)
return nil return nil
} }
@ -1704,6 +1708,6 @@ func (c *Conn) sendKeyUpdateLocked() error {
if err := c.flushHandshake(); err != nil { if err := c.flushHandshake(); err != nil {
return err return err
} }
c.out.doKeyUpdate(c, false) c.out.doKeyUpdate(c, true)
return nil return nil
} }

View File

@ -2166,6 +2166,16 @@ func addBasicTests() {
shouldFail: true, shouldFail: true,
expectedError: ":WRONG_VERSION_NUMBER:", expectedError: ":WRONG_VERSION_NUMBER:",
}, },
{
testType: clientTest,
name: "KeyUpdate",
config: Config{
MaxVersion: VersionTLS13,
Bugs: ProtocolBugs{
SendKeyUpdateBeforeEveryAppDataRecord: true,
},
},
},
} }
testCases = append(testCases, basicTests...) testCases = append(testCases, basicTests...)
} }

View File

@ -453,7 +453,22 @@ int tls13_prepare_finished(SSL *ssl) {
return 1; return 1;
} }
static int tls13_receive_key_update(SSL *ssl) {
if (ssl->init_num != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return 0;
}
// TODO(svaldez): Send KeyUpdate.
return tls13_rotate_traffic_key(ssl, evp_aead_open);
}
int tls13_post_handshake(SSL *ssl) { int tls13_post_handshake(SSL *ssl) {
if (ssl->s3->tmp.message_type == SSL3_MT_KEY_UPDATE) {
return tls13_receive_key_update(ssl);
}
if (ssl->s3->tmp.message_type == SSL3_MT_NEW_SESSION_TICKET && if (ssl->s3->tmp.message_type == SSL3_MT_NEW_SESSION_TICKET &&
!ssl->server) { !ssl->server) {
// TODO(svaldez): Handle NewSessionTicket. // TODO(svaldez): Handle NewSessionTicket.
@ -461,7 +476,6 @@ int tls13_post_handshake(SSL *ssl) {
} }
// TODO(svaldez): Handle post-handshake authentication. // TODO(svaldez): Handle post-handshake authentication.
// TODO(svaldez): Handle KeyUpdate.
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);

View File

@ -176,7 +176,7 @@ int tls13_set_traffic_key(SSL *ssl, enum tls_record_type_t type,
const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)); const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
size_t mac_secret_len, fixed_iv_len; size_t mac_secret_len, fixed_iv_len;
if (!ssl_cipher_get_evp_aead(&aead, &mac_secret_len, &fixed_iv_len, if (!ssl_cipher_get_evp_aead(&aead, &mac_secret_len, &fixed_iv_len,
ssl->s3->new_session->cipher, SSL_get_session(ssl)->cipher,
ssl3_protocol_version(ssl))) { ssl3_protocol_version(ssl))) {
return 0; return 0;
} }
@ -207,7 +207,7 @@ int tls13_set_traffic_key(SSL *ssl, enum tls_record_type_t type,
} }
SSL_AEAD_CTX *traffic_aead = SSL_AEAD_CTX_new( SSL_AEAD_CTX *traffic_aead = SSL_AEAD_CTX_new(
direction, ssl3_protocol_version(ssl), ssl->s3->new_session->cipher, key, direction, ssl3_protocol_version(ssl), SSL_get_session(ssl)->cipher, key,
key_len, NULL, 0, iv, iv_len); key_len, NULL, 0, iv, iv_len);
if (traffic_aead == NULL) { if (traffic_aead == NULL) {
return 0; return 0;
@ -225,10 +225,10 @@ int tls13_set_traffic_key(SSL *ssl, enum tls_record_type_t type,
/* Save the traffic secret. */ /* Save the traffic secret. */
if (direction == evp_aead_open) { if (direction == evp_aead_open) {
memcpy(ssl->s3->read_traffic_secret, traffic_secret, traffic_secret_len); memmove(ssl->s3->read_traffic_secret, traffic_secret, traffic_secret_len);
ssl->s3->read_traffic_secret_len = traffic_secret_len; ssl->s3->read_traffic_secret_len = traffic_secret_len;
} else { } else {
memcpy(ssl->s3->write_traffic_secret, traffic_secret, traffic_secret_len); memmove(ssl->s3->write_traffic_secret, traffic_secret, traffic_secret_len);
ssl->s3->write_traffic_secret_len = traffic_secret_len; ssl->s3->write_traffic_secret_len = traffic_secret_len;
} }
@ -267,6 +267,29 @@ int tls13_derive_traffic_secret_0(SSL *ssl) {
hs->hash_len); hs->hash_len);
} }
int tls13_rotate_traffic_key(SSL *ssl, enum evp_aead_direction_t direction) {
const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
uint8_t *secret;
size_t secret_len;
if (direction == evp_aead_open) {
secret = ssl->s3->read_traffic_secret;
secret_len = ssl->s3->read_traffic_secret_len;
} else {
secret = ssl->s3->write_traffic_secret;
secret_len = ssl->s3->write_traffic_secret_len;
}
if (!hkdf_expand_label(secret, digest, secret, secret_len,
(const uint8_t *)kTLS13LabelApplicationTraffic,
strlen(kTLS13LabelApplicationTraffic), NULL, 0,
secret_len)) {
return 0;
}
return tls13_set_traffic_key(ssl, type_data, direction, secret, secret_len);
}
static const char kTLS13LabelExporter[] = "exporter master secret"; static const char kTLS13LabelExporter[] = "exporter master secret";
static const char kTLS13LabelResumption[] = "resumption master secret"; static const char kTLS13LabelResumption[] = "resumption master secret";