diff --git a/include/openssl/ssl3.h b/include/openssl/ssl3.h index aca19223065ba..4ca434e760ed8 100644 --- a/include/openssl/ssl3.h +++ b/include/openssl/ssl3.h @@ -264,11 +264,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 diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c index 00379ea601b7c..4a7e59bc990bd 100644 --- a/ssl/record/rec_layer_s3.c +++ b/ssl/record/rec_layer_s3.c @@ -395,7 +395,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len) if (type == SSL3_RT_APPLICATION_DATA && u_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]; @@ -791,7 +791,7 @@ int do_ssl3_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[j], &(outbuf[j][wr[j].length + eivlen]), 1) < 0) @@ -814,7 +814,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf, goto err; for (j = 0; j < numpipes; j++) { - if (SSL_USE_ETM(s) && mac_size != 0) { + if (SSL_WRITE_ETM(s) && mac_size != 0) { if (s->method->ssl3_enc->mac(s, &wr[j], outbuf[j] + wr[j].length, 1) < 0) goto err; diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c index e5cbd614cae44..1f07933924591 100644 --- a/ssl/record/ssl3_record.c +++ b/ssl/record/ssl3_record.c @@ -346,7 +346,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; mac_size = EVP_MD_CTX_size(s->read_hash); OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE); @@ -393,7 +393,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]; @@ -823,7 +823,7 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, unsigned int 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) mac_size = EVP_MD_CTX_size(s->read_hash); if ((bs != 1) && !send) { int tmpret; @@ -997,7 +997,7 @@ int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int send) header[11] = (rec->length) >> 8; header[12] = (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)) { /* @@ -1022,7 +1022,7 @@ int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int send) EVP_MD_CTX_free(hmac); return -1; } - 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)) { diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 1586a46f63580..08de52eea2cad 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -378,7 +378,8 @@ # define SSL_CLIENT_USE_SIGALGS(s) \ SSL_CLIENT_USE_TLS1_2_CIPHERS(s) -# define SSL_USE_ETM(s) (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC) +# define SSL_READ_ETM(s) (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC_READ) +# define SSL_WRITE_ETM(s) (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE) /* Mostly for SSLv3 */ # define SSL_PKEY_RSA_ENC 0 @@ -1110,6 +1111,10 @@ struct ssl_st { */ unsigned char *alpn_client_proto_list; unsigned alpn_client_proto_list_len; + + /* Set to one if we have negotiated ETM */ + int tlsext_use_etm; + /*- * 1 if we are renegotiating. * 2 if we are a server and are inside a handshake diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index 4aa5ddd18a3c7..0fb88af249e1e 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c @@ -130,6 +130,11 @@ int tls1_change_cipher_state(SSL *s, int which) #endif if (which & SSL3_CC_READ) { + if (s->tlsext_use_etm) + s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC_READ; + else + s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC_READ; + if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC) s->mac_flags |= SSL_MAC_FLAG_READ_MAC_STREAM; else @@ -168,6 +173,11 @@ int tls1_change_cipher_state(SSL *s, int which) mac_secret = &(s->s3->read_mac_secret[0]); mac_secret_size = &(s->s3->read_mac_secret_size); } else { + if (s->tlsext_use_etm) + s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE; + else + s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE; + if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC) s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM; else @@ -367,9 +377,8 @@ int tls1_setup_key_block(SSL *s) if (s->s3->tmp.key_block_length != 0) return (1); - if (!ssl_cipher_get_evp - (s->session, &c, &hash, &mac_type, &mac_secret_size, &comp, - SSL_USE_ETM(s))) { + if (!ssl_cipher_get_evp(s->session, &c, &hash, &mac_type, &mac_secret_size, + &comp, s->tlsext_use_etm)) { SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK, SSL_R_CIPHER_OR_HASH_UNAVAILABLE); return (0); } diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index b51d60a7cc5da..b2688f6552b34 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -1674,7 +1674,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, #endif if (!custom_ext_add(s, 1, &ret, limit, al)) return NULL; - if (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC) { + if (s->tlsext_use_etm) { /* * Don't use encrypt_then_mac if AEAD or RC4 might want to disable * for other cases too. @@ -1683,7 +1683,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, || s->s3->tmp.new_cipher->algorithm_enc == SSL_RC4 || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12) - s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC; + s->tlsext_use_etm = 0; else { /*- * check for enough space. @@ -1916,7 +1916,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, PACKET *pkt, int *al) /* Clear any signature algorithms extension received */ OPENSSL_free(s->s3->tmp.peer_sigalgs); s->s3->tmp.peer_sigalgs = NULL; - s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC; + s->tlsext_use_etm = 0; #ifndef OPENSSL_NO_SRP OPENSSL_free(s->srp_ctx.login); @@ -2264,7 +2264,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, PACKET *pkt, int *al) } #endif else if (type == TLSEXT_TYPE_encrypt_then_mac) - s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC; + s->tlsext_use_etm = 1; /* * Note: extended master secret extension handled in * tls_check_serverhello_tlsext_early() @@ -2366,7 +2366,7 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al) SSL_DTLSEXT_HB_DONT_SEND_REQUESTS); #endif - s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC; + s->tlsext_use_etm = 0; s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS; @@ -2585,7 +2585,7 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al) /* Ignore if inappropriate ciphersuite */ if (s->s3->tmp.new_cipher->algorithm_mac != SSL_AEAD && s->s3->tmp.new_cipher->algorithm_enc != SSL_RC4) - s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC; + s->tlsext_use_etm = 1; } else if (type == TLSEXT_TYPE_extended_master_secret) { s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS; if (!s->hit)