Commit 731f4314 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Add heartbeat extension bounds check.

A missing bounds check in the handling of the TLS heartbeat extension
can be used to reveal up to 64k of memory to a connected client or
server.

Thanks for Neel Mehta of Google Security for discovering this bug and to
Adam Langley <agl@chromium.org> and Bodo Moeller <bmoeller@acm.org> for
preparing the fix (CVE-2014-0160)
(cherry picked from commit 96db9023)
parent 4e6c12f3
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -4,6 +4,15 @@

 Changes between 1.0.2 and 1.1.0  [xx XXX xxxx]

  *) A missing bounds check in the handling of the TLS heartbeat extension
     can be used to reveal up to 64k of memory to a connected client or
     server.

     Thanks for Neel Mehta of Google Security for discovering this bug and to
     Adam Langley <agl@chromium.org> and Bodo Moeller <bmoeller@acm.org> for
     preparing the fix (CVE-2014-0160)
     [Adam Langley, Bodo Moeller]

  *) Fix for the attack described in the paper "Recovering OpenSSL
     ECDSA Nonces Using the FLUSH+RELOAD Cache Side-channel Attack"
     by Yuval Yarom and Naomi Benger. Details can be obtained from:
+18 −8
Original line number Diff line number Diff line
@@ -1330,26 +1330,36 @@ dtls1_process_heartbeat(SSL *s)
	unsigned int payload;
	unsigned int padding = 16; /* Use minimum padding */

	/* Read type and payload length first */
	hbtype = *p++;
	n2s(p, payload);
	pl = p;

	if (s->msg_callback)
		s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
			&s->s3->rrec.data[0], s->s3->rrec.length,
			s, s->msg_callback_arg);

	/* Read type and payload length first */
	if (1 + 2 + 16 > s->s3->rrec.length)
		return 0; /* silently discard */
	hbtype = *p++;
	n2s(p, payload);
	if (1 + 2 + payload + 16 > s->s3->rrec.length)
		return 0; /* silently discard per RFC 6520 sec. 4 */
	pl = p;

	if (hbtype == TLS1_HB_REQUEST)
		{
		unsigned char *buffer, *bp;
		unsigned int write_length = 1 /* heartbeat type */ +
					    2 /* heartbeat length */ +
					    payload + padding;
		int r;

		if (write_length > SSL3_RT_MAX_PLAIN_LENGTH)
			return 0;

		/* Allocate memory for the response, size is 1 byte
		 * message type, plus 2 bytes payload length, plus
		 * payload, plus padding
		 */
		buffer = OPENSSL_malloc(1 + 2 + payload + padding);
		buffer = OPENSSL_malloc(write_length);
		bp = buffer;

		/* Enter response type, length and copy payload */
@@ -1360,11 +1370,11 @@ dtls1_process_heartbeat(SSL *s)
		/* Random padding */
		RAND_pseudo_bytes(bp, padding);

		r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding);
		r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, write_length);

		if (r >= 0 && s->msg_callback)
			s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,
				buffer, 3 + payload + padding,
				buffer, write_length,
				s, s->msg_callback_arg);

		OPENSSL_free(buffer);
+9 −5
Original line number Diff line number Diff line
@@ -3969,16 +3969,20 @@ tls1_process_heartbeat(SSL *s)
	unsigned int payload;
	unsigned int padding = 16; /* Use minimum padding */

	/* Read type and payload length first */
	hbtype = *p++;
	n2s(p, payload);
	pl = p;

	if (s->msg_callback)
		s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
			&s->s3->rrec.data[0], s->s3->rrec.length,
			s, s->msg_callback_arg);

	/* Read type and payload length first */
	if (1 + 2 + 16 > s->s3->rrec.length)
		return 0; /* silently discard */
	hbtype = *p++;
	n2s(p, payload);
	if (1 + 2 + payload + 16 > s->s3->rrec.length)
		return 0; /* silently discard per RFC 6520 sec. 4 */
	pl = p;

	if (hbtype == TLS1_HB_REQUEST)
		{
		unsigned char *buffer, *bp;