Remove TLS heartbeat, disable DTLS heartbeat

To enable heartbeats for DTLS, configure with enable-heartbeats.
Heartbeats for TLS have been completely removed.

This addresses RT 3647

Reviewed-by: Richard Levitte <levitte@openssl.org>
This commit is contained in:
Rich Salz
2016-01-25 13:30:37 -05:00
committed by Rich Salz
parent f3f1cf8444
commit 22e3dcb780
17 changed files with 94 additions and 339 deletions

View File

@@ -1389,20 +1389,22 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf,
i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &ret);
}
#ifndef OPENSSL_NO_HEARTBEATS
/* Add Heartbeat extension */
if ((limit - ret - 4 - 1) < 0)
return NULL;
s2n(TLSEXT_TYPE_heartbeat, ret);
s2n(1, ret);
/*-
* Set mode:
* 1: peer may send requests
* 2: peer not allowed to send requests
*/
if (s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_RECV_REQUESTS)
*(ret++) = SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
else
*(ret++) = SSL_TLSEXT_HB_ENABLED;
if (SSL_IS_DTLS(s)) {
/* Add Heartbeat extension */
if ((limit - ret - 4 - 1) < 0)
return NULL;
s2n(TLSEXT_TYPE_heartbeat, ret);
s2n(1, ret);
/*-
* Set mode:
* 1: peer may send requests
* 2: peer not allowed to send requests
*/
if (s->tlsext_heartbeat & SSL_DTLSEXT_HB_DONT_RECV_REQUESTS)
*(ret++) = SSL_DTLSEXT_HB_DONT_SEND_REQUESTS;
else
*(ret++) = SSL_DTLSEXT_HB_ENABLED;
}
#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
@@ -1637,7 +1639,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
}
#ifndef OPENSSL_NO_HEARTBEATS
/* Add Heartbeat extension if we've received one */
if (s->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED) {
if (SSL_IS_DTLS(s) && (s->tlsext_heartbeat & SSL_DTLSEXT_HB_ENABLED)) {
if ((limit - ret - 4 - 1) < 0)
return NULL;
s2n(TLSEXT_TYPE_heartbeat, ret);
@@ -1647,10 +1649,10 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
* 1: peer may send requests
* 2: peer not allowed to send requests
*/
if (s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_RECV_REQUESTS)
*(ret++) = SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
if (s->tlsext_heartbeat & SSL_DTLSEXT_HB_DONT_RECV_REQUESTS)
*(ret++) = SSL_DTLSEXT_HB_DONT_SEND_REQUESTS;
else
*(ret++) = SSL_TLSEXT_HB_ENABLED;
*(ret++) = SSL_DTLSEXT_HB_ENABLED;
}
#endif
@@ -1878,8 +1880,8 @@ static int ssl_scan_clienthello_tlsext(SSL *s, PACKET *pkt, int *al)
OPENSSL_free(s->s3->alpn_selected);
s->s3->alpn_selected = NULL;
#ifndef OPENSSL_NO_HEARTBEATS
s->tlsext_heartbeat &= ~(SSL_TLSEXT_HB_ENABLED |
SSL_TLSEXT_HB_DONT_SEND_REQUESTS);
s->tlsext_heartbeat &= ~(SSL_DTLSEXT_HB_ENABLED |
SSL_DTLSEXT_HB_DONT_SEND_REQUESTS);
#endif
#ifndef OPENSSL_NO_EC
@@ -2197,7 +2199,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, PACKET *pkt, int *al)
s->tlsext_status_type = -1;
}
#ifndef OPENSSL_NO_HEARTBEATS
else if (type == TLSEXT_TYPE_heartbeat) {
else if (SSL_IS_DTLS(s) && type == TLSEXT_TYPE_heartbeat) {
unsigned int hbtype;
if (!PACKET_get_1(&subpkt, &hbtype)
@@ -2207,11 +2209,11 @@ static int ssl_scan_clienthello_tlsext(SSL *s, PACKET *pkt, int *al)
}
switch (hbtype) {
case 0x01: /* Client allows us to send HB requests */
s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED;
s->tlsext_heartbeat |= SSL_DTLSEXT_HB_ENABLED;
break;
case 0x02: /* Client doesn't accept HB requests */
s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED;
s->tlsext_heartbeat |= SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
s->tlsext_heartbeat |= SSL_DTLSEXT_HB_ENABLED;
s->tlsext_heartbeat |= SSL_DTLSEXT_HB_DONT_SEND_REQUESTS;
break;
default:
*al = SSL_AD_ILLEGAL_PARAMETER;
@@ -2356,8 +2358,8 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al)
OPENSSL_free(s->s3->alpn_selected);
s->s3->alpn_selected = NULL;
#ifndef OPENSSL_NO_HEARTBEATS
s->tlsext_heartbeat &= ~(SSL_TLSEXT_HB_ENABLED |
SSL_TLSEXT_HB_DONT_SEND_REQUESTS);
s->tlsext_heartbeat &= ~(SSL_DTLSEXT_HB_ENABLED |
SSL_DTLSEXT_HB_DONT_SEND_REQUESTS);
#endif
#ifdef TLSEXT_TYPE_encrypt_then_mac
@@ -2519,7 +2521,7 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al)
s->s3->alpn_selected_len = len;
}
#ifndef OPENSSL_NO_HEARTBEATS
else if (type == TLSEXT_TYPE_heartbeat) {
else if (SSL_IS_DTLS(s) && type == TLSEXT_TYPE_heartbeat) {
unsigned int hbtype;
if (!PACKET_get_1(&spkt, &hbtype)) {
*al = SSL_AD_DECODE_ERROR;
@@ -2527,11 +2529,11 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al)
}
switch (hbtype) {
case 0x01: /* Server allows us to send HB requests */
s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED;
s->tlsext_heartbeat |= SSL_DTLSEXT_HB_ENABLED;
break;
case 0x02: /* Server doesn't accept HB requests */
s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED;
s->tlsext_heartbeat |= SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
s->tlsext_heartbeat |= SSL_DTLSEXT_HB_ENABLED;
s->tlsext_heartbeat |= SSL_DTLSEXT_HB_DONT_SEND_REQUESTS;
break;
default:
*al = SSL_AD_ILLEGAL_PARAMETER;
@@ -3627,160 +3629,6 @@ int SSL_get_shared_sigalgs(SSL *s, int idx,
return s->cert->shared_sigalgslen;
}
#ifndef OPENSSL_NO_HEARTBEATS
int tls1_process_heartbeat(SSL *s, unsigned char *p, unsigned int length)
{
unsigned char *pl;
unsigned short hbtype;
unsigned int payload;
unsigned int padding = 16; /* Use minimum padding */
if (s->msg_callback)
s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
p, length,
s, s->msg_callback_arg);
/* Read type and payload length first */
if (1 + 2 + 16 > length)
return 0; /* silently discard */
hbtype = *p++;
n2s(p, payload);
if (1 + 2 + payload + 16 > length)
return 0; /* silently discard per RFC 6520 sec. 4 */
pl = p;
if (hbtype == TLS1_HB_REQUEST) {
unsigned char *buffer, *bp;
int r;
/*
* Allocate memory for the response, size is 1 bytes message type,
* plus 2 bytes payload length, plus payload, plus padding
*/
buffer = OPENSSL_malloc(1 + 2 + payload + padding);
if (buffer == NULL) {
SSLerr(SSL_F_TLS1_PROCESS_HEARTBEAT, ERR_R_MALLOC_FAILURE);
return -1;
}
bp = buffer;
/* Enter response type, length and copy payload */
*bp++ = TLS1_HB_RESPONSE;
s2n(payload, bp);
memcpy(bp, pl, payload);
bp += payload;
/* Random padding */
if (RAND_bytes(bp, padding) <= 0) {
OPENSSL_free(buffer);
return -1;
}
r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buffer,
3 + payload + padding);
if (r >= 0 && s->msg_callback)
s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,
buffer, 3 + payload + padding,
s, s->msg_callback_arg);
OPENSSL_free(buffer);
if (r < 0)
return r;
} else if (hbtype == TLS1_HB_RESPONSE) {
unsigned int seq;
/*
* We only send sequence numbers (2 bytes unsigned int), and 16
* random bytes, so we just try to read the sequence number
*/
n2s(pl, seq);
if (payload == 18 && seq == s->tlsext_hb_seq) {
s->tlsext_hb_seq++;
s->tlsext_hb_pending = 0;
}
}
return 0;
}
int tls1_heartbeat(SSL *s)
{
unsigned char *buf, *p;
int ret = -1;
unsigned int payload = 18; /* Sequence number + random bytes */
unsigned int padding = 16; /* Use minimum padding */
/* Only send if peer supports and accepts HB requests... */
if (!(s->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED) ||
s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_SEND_REQUESTS) {
SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT);
return -1;
}
/* ...and there is none in flight yet... */
if (s->tlsext_hb_pending) {
SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_TLS_HEARTBEAT_PENDING);
return -1;
}
/* ...and no handshake in progress. */
if (SSL_in_init(s) || ossl_statem_get_in_handshake(s)) {
SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_UNEXPECTED_MESSAGE);
return -1;
}
/*-
* Create HeartBeat message, we just use a sequence number
* as payload to distuingish different messages and add
* some random stuff.
* - Message Type, 1 byte
* - Payload Length, 2 bytes (unsigned int)
* - Payload, the sequence number (2 bytes uint)
* - Payload, random bytes (16 bytes uint)
* - Padding
*/
buf = OPENSSL_malloc(1 + 2 + payload + padding);
if (buf == NULL) {
SSLerr(SSL_F_TLS1_HEARTBEAT, ERR_R_MALLOC_FAILURE);
return -1;
}
p = buf;
/* Message Type */
*p++ = TLS1_HB_REQUEST;
/* Payload length (18 bytes here) */
s2n(payload, p);
/* Sequence number */
s2n(s->tlsext_hb_seq, p);
/* 16 random bytes */
if (RAND_bytes(p, 16) <= 0) {
SSLerr(SSL_F_TLS1_HEARTBEAT, ERR_R_INTERNAL_ERROR);
goto err;
}
p += 16;
/* Random padding */
if (RAND_bytes(p, padding) <= 0) {
SSLerr(SSL_F_TLS1_HEARTBEAT, ERR_R_INTERNAL_ERROR);
goto err;
}
ret = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buf, 3 + payload + padding);
if (ret >= 0) {
if (s->msg_callback)
s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,
buf, 3 + payload + padding,
s, s->msg_callback_arg);
s->tlsext_hb_pending = 1;
}
err:
OPENSSL_free(buf);
return ret;
}
#endif
#define MAX_SIGALGLEN (TLSEXT_hash_num * TLSEXT_signature_num * 2)
typedef struct {