Commit 28a31a0a authored by Matt Caswell's avatar Matt Caswell
Browse files

Don't change the state of the ETM flags until CCS processing



In 1.1.0 changing the ciphersuite during a renegotiation can result in
a crash leading to a DoS attack. In master this does not occur with TLS
(instead you get an internal error, which is still wrong but not a security
issue) - but the problem still exists in the DTLS code.

The problem is caused by changing the flag indicating whether to use ETM
or not immediately on negotiation of ETM, rather than at CCS. Therefore,
during a renegotiation, if the ETM state is changing (usually due to a
change of ciphersuite), then an error/crash will occur.

Due to the fact that there are separate CCS messages for read and write
we actually now need two flags to determine whether to use ETM or not.

CVE-2017-3733

Reviewed-by: default avatarRichard Levitte <levitte@openssl.org>
parent cc22cd54
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -265,11 +265,14 @@ extern "C" {
# define TLS1_FLAGS_SKIP_CERT_VERIFY             0x0010

/* Set if we encrypt then mac instead of usual mac then encrypt */
# define TLS1_FLAGS_ENCRYPT_THEN_MAC             0x0100
# define TLS1_FLAGS_ENCRYPT_THEN_MAC_READ        0x0100
# define TLS1_FLAGS_ENCRYPT_THEN_MAC             TLS1_FLAGS_ENCRYPT_THEN_MAC_READ

/* Set if extended master secret extension received from peer */
# define TLS1_FLAGS_RECEIVED_EXTMS               0x0200

# define TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE       0x0400

# define SSL3_MT_HELLO_REQUEST                   0
# define SSL3_MT_CLIENT_HELLO                    1
# define SSL3_MT_SERVER_HELLO                    2
+1 −1
Original line number Diff line number Diff line
@@ -937,7 +937,7 @@ size_t DTLS_get_data_mtu(const SSL *s)
                                 &blocksize, &ext_overhead))
        return 0;

    if (SSL_USE_ETM(s))
    if (SSL_READ_ETM(s))
        ext_overhead += mac_overhead;
    else
        int_overhead += mac_overhead;
+2 −2
Original line number Diff line number Diff line
@@ -1029,7 +1029,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
     * wb->buf
     */

    if (!SSL_USE_ETM(s) && mac_size != 0) {
    if (!SSL_WRITE_ETM(s) && mac_size != 0) {
        if (!s->method->ssl3_enc->mac(s, &wr,
                                      &(p[SSL3_RECORD_get_length(&wr) + eivlen]),
                                      1))
@@ -1047,7 +1047,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
    if (s->method->ssl3_enc->enc(s, &wr, 1, 1) < 1)
        goto err;

    if (SSL_USE_ETM(s) && mac_size != 0) {
    if (SSL_WRITE_ETM(s) && mac_size != 0) {
        if (!s->method->ssl3_enc->mac(s, &wr,
                                      &(p[SSL3_RECORD_get_length(&wr)]), 1))
            goto err;
+3 −3
Original line number Diff line number Diff line
@@ -401,7 +401,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, size_t len,
    if (type == SSL3_RT_APPLICATION_DATA &&
        len >= 4 * (max_send_fragment = s->max_send_fragment) &&
        s->compress == NULL && s->msg_callback == NULL &&
        !SSL_USE_ETM(s) && SSL_USE_EXPLICIT_IV(s) &&
        !SSL_WRITE_ETM(s) && SSL_USE_EXPLICIT_IV(s) &&
        EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx)) &
        EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) {
        unsigned char aad[13];
@@ -870,7 +870,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
         * in the wb->buf
         */

        if (!SSL_USE_ETM(s) && mac_size != 0) {
        if (!SSL_WRITE_ETM(s) && mac_size != 0) {
            unsigned char *mac;

            if (!WPACKET_allocate_bytes(thispkt, mac_size, &mac)
@@ -923,7 +923,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
            SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
            goto err;
        }
        if (SSL_USE_ETM(s) && mac_size != 0) {
        if (SSL_WRITE_ETM(s) && mac_size != 0) {
            unsigned char *mac;

            if (!WPACKET_allocate_bytes(thispkt, mac_size, &mac)
+7 −7
Original line number Diff line number Diff line
@@ -383,7 +383,7 @@ int ssl3_get_record(SSL *s)
     * If in encrypt-then-mac mode calculate mac from encrypted record. All
     * the details below are public so no timing details can leak.
     */
    if (SSL_USE_ETM(s) && s->read_hash) {
    if (SSL_READ_ETM(s) && s->read_hash) {
        unsigned char *mac;
        /* TODO(size_t): convert this to do size_t properly */
        imac_size = EVP_MD_CTX_size(s->read_hash);
@@ -440,7 +440,7 @@ int ssl3_get_record(SSL *s)
    /* r->length is now the compressed data plus mac */
    if ((sess != NULL) &&
        (s->enc_read_ctx != NULL) &&
        (EVP_MD_CTX_md(s->read_hash) != NULL) && !SSL_USE_ETM(s)) {
        (!SSL_READ_ETM(s) && EVP_MD_CTX_md(s->read_hash) != NULL)) {
        /* s->read_hash != NULL => mac_size != -1 */
        unsigned char *mac = NULL;
        unsigned char mac_tmp[EVP_MAX_MD_SIZE];
@@ -915,7 +915,7 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int send)
        }

        ret = 1;
        if (!SSL_USE_ETM(s) && EVP_MD_CTX_md(s->read_hash) != NULL) {
        if (!SSL_READ_ETM(s) && EVP_MD_CTX_md(s->read_hash) != NULL) {
            imac_size = EVP_MD_CTX_size(s->read_hash);
            if (imac_size < 0)
                return -1;
@@ -1092,7 +1092,7 @@ int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int send)
    header[11] = (unsigned char)(rec->length >> 8);
    header[12] = (unsigned char)(rec->length & 0xff);

    if (!send && !SSL_USE_ETM(ssl) &&
    if (!send && !SSL_READ_ETM(ssl) &&
        EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
        ssl3_cbc_record_digest_supported(mac_ctx)) {
        /*
@@ -1118,7 +1118,7 @@ int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int send)
            EVP_MD_CTX_free(hmac);
            return 0;
        }
        if (!send && !SSL_USE_ETM(ssl) && FIPS_mode())
        if (!send && !SSL_READ_ETM(ssl) && FIPS_mode())
            if (!tls_fips_digest_extra(ssl->enc_read_ctx,
                                       mac_ctx, rec->input,
                                       rec->length, rec->orig_len)) {
@@ -1408,7 +1408,7 @@ int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
    rr->data = rr->input;
    rr->orig_len = rr->length;

    if (SSL_USE_ETM(s) && s->read_hash) {
    if (SSL_READ_ETM(s) && s->read_hash) {
        unsigned char *mac;
        mac_size = EVP_MD_CTX_size(s->read_hash);
        OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE);
@@ -1452,7 +1452,7 @@ int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
#endif

    /* r->length is now the compressed data plus mac */
    if ((sess != NULL) && !SSL_USE_ETM(s) &&
    if ((sess != NULL) && !SSL_READ_ETM(s) &&
        (s->enc_read_ctx != NULL) && (EVP_MD_CTX_md(s->read_hash) != NULL)) {
        /* s->read_hash != NULL => mac_size != -1 */
        unsigned char *mac = NULL;
Loading